Показ дописів із міткою vkontakte. Показати всі дописи
Показ дописів із міткою vkontakte. Показати всі дописи

вівторок, 30 квітня 2013 р.

Отримання улюблених аудіозаписів з Last.fm

Почитав тут статтю Получение любимых аудиозаписей с pandora.com, подумав і придумав subj.
Отже, з Last.fm будемо отримувати список назв пісень і виконавців, потім за допомогою API ВКонтакте будемо їх скачувати.

Крок 1. Йдем на Last.fm, і витягуємо список улюблених пісень користувача.

Для тих хто не знає, Last.fm має API, що дозволяє будь-якому користувачеві створювати свої власні програми з використанням даних Last.fm. Для роботи з API потрібно отримати API Key і Secret. Йдемо на http://www.last.fm/api і створюємо новий аккаунт для некомерційного використання.

ruby-lastfm - інтерфейс для Web-сервісів Last.fm v2.0.
Тепер нам потрібно отримати token:
lastfm = Lastfm.new(lastfm_api_key, lastfm_api_secret)
lastfm_token = lastfm.auth.get_token

Далі нам пропонують відкрити 'http://www.last.fm/api/auth/?api_key=xxxxxxxxxxx&token=xxxxxxxx' і надати права додатку.

Спробуємо змоделювати цей запит. Але спочатку потрібно авторизуватися на сайті Last.fm за допомогою імені і паролю. Використовуємо бібліотеку Mechanize:
mech = Mechanize.new do |a|
  a.user_agent_alias = 'Linux Firefox'
  a.verify_mode = OpenSSL::SSL::VERIFY_NONE
  a.follow_meta_refresh = true
end

login_page = mech.get('https://last.fm/login')
login_form = login_page.form_with(action: '/login')

login_form.username = lastfm_username
login_form.password = lastfm_password

page = login_form.submit

if page.uri.to_s == 'http://www.last.fm/home'
  puts "Login successful!"
else
  puts page.uri.to_s
  exit
end

Якщо авторизація пройшла успішно, надаємо права додатку:
grantaccess_url = "http://www.last.fm/api/auth/?api_key=#{lastfm_api_key}&token=#{lastfm_token}"
grantaccess_page = mech.get(grantaccess_url)

grantaccess_form = grantaccess_page.form_with(action: '/api/grantaccess')
grantaccess_form.submit

Отже, тепер ми можемо витягнути всю цікаву для нас інформацію:
lastfm.session = lastfm.auth.get_session(:token => lastfm_token)['key']
tracks = lastfm.user.get_loved_tracks(user: lastfm_username)

Перший крок пройдений! :)

Крок другий. Пошук і скачування записів з vk.com.
Авторизуємося ВКонаткте:
vk = Vkontakte::Client.new(vk_client_id)
vk.login!(vk_email, vk_password, scope = 'audio')

Використовуємо API функцію пошуку аудіо:
str = "#{track['artist']['name']} - #{track['name']}"
audio = vk.api.audio_search(q: str, sort: 2)[1]

Вона повертає найпопулярніший результат пошуку рядка str (серед аудіозаписів).

Тепер ми знаємо url для скачування. Завантажити можна за допомогою стандартної функції.
path = "#{downloaded_folder}/" + "#{audio['artist']} - #{audio['title']}.mp3"
File.open(path, 'wb') do |saved_file|
  open(audio['url'], 'rb') do |read_file|
    saved_file.write(read_file.read)
  end
end

В результаті вийшов ось такий скрипт:
https://gist.github.com/mamantoha/5488722

Як з ним працювати:
  • Скрипт вимагає встановленого Ruby і гемів mechanize, ruby-lastfm, vkontakte
  • Потрібно отримати ключі для Last.fm(lastfm_api_key, lastfm_secret) і ВКонтакте(vk_client_id)
  • downloaded_folder - директорія, куди буде зберігатися скачана музика
  • lastfm_username і lastfm_password - ваш логін і пароль на Last.fm
  • vk_email і vk_password - ваш логін і пароль на Vk.com

Відповідні параметри прописати в тілі скрипта.

вівторок, 3 липня 2012 р.

ВКонтакте → Авторизація додатків з Ruby і Net::HTTP

На днях виникло бажання переписати код своєї бібліотеки для для авторизації ВКонтакте і здійснення запитів до API, використовуючи тільки стандартні модулі Ruby.

Для того, щоб прикинутися справжнім браузером, просто завантажувати потрібні сторінки недостатньо. Як мінімум, потрібно коректно обробляти куки і редіректи. Для цього у попередній статі я використовував чудову бібліотеку Mechanize.

Спочатку встановимо необхідні параметри.

Детально про параметри звернення можна прочитати в документації.
client_id - ідентифікатор вашого додатку.
Тут слід зазначити, що ми будемо використовувати параметр display із значенням wap, так в цьому варіанті сторінки практично відсутній JavaScript.
scope являє собою список прав, до яких ми хочемо отримати доступ.

Звертаємося до сторінки авторизації




Парсимо відповідь


Подивимося на код сторінки авторизації. Найбільше нас буде цікавити наступна частина:


Для подальшої відправки форми необхідно розпарсити всі input'и (и тому числі і приховані), а також URL, на який сабмітиться форма.


Авторизуємось


Підставляємо в параметри запиту електронну пошту та пароль користувача і відправляємо форму:


Отримуємо куку




Встановлюємо куку




Отримуємо код


Наступним етапом, якщо користувач цього ще не робив, треба дати додатку ті права, які ми запитували в параметрі scope. Для цього нам буде запропонована сторінка з формою.

В результаті отримуємо відповідь наступного вигляду:
http://oauth.vk.com/blank.html#code=xxxxxxxxxxxxxxxxxx



Даний метод авторизації не є офіційним і може змінитися.

четвер, 17 травня 2012 р.

Оновлюємо статус ВКонтакте за допомогою Ruby

Сьогодні вечором виникло бажання, щоб на моїй сторінці ВКонтакте відображався таймер зворотнього відліку до початку Євро-2012 прямо в статусі. Написати простенький скрипт на Ruby для такого достатньо просто.
З інструментів я використовував свою бібліотеку для роботи з API ВКонтакте. Якщо комусь цікаво, як вона працює, можете почитати статтю ВКонтакте → Авторизація Standalone-додатків використовуючи OAuth 2.0 на прикладі Ruby і Mechanize.

Не вдаючись в подробиці, ось посилання на приклад скрипта.

Здавалось би залишилось додати скрипт у cron і насолоджуватись результатом.
Наступний рядок у /etc/crontab не приніс бажаних результатів.
*/1 * * * * user ruby /home/user/days_to_euro.rb
Скрипт всього-на-всього не виконувався.
Причиною проблеми виявився Ruby Version Manager(RVM). Змінюємо на наступний рядок.
*/1 * * * * user bash -c 'source /home/user/.rvm/scripts/rvm && /usr/bin/env ruby /home/user/days_to_euro.rb'

І вуаля: тепер скрипт успішно виконується і так же успішно завершує роботу з помилкою:
`default_gemfile': Could not locate Gemfile (Bundler::GemfileNotFound)
Це відбувається тому, Bundler шукає Gemfile в каталозі в якому виконується, а Gemfile там звісно ж немає.
Потрібно вказати де шукати Gemfile.
ENV['BUNDLE_GEMFILE'] = File.join(File.dirname(__FILE__) ,'Gemfile')
Вищевказаний рядок потрібно додати у шапку скрипта.

Тепер все добре і скрипт працює.

P.S. До Євро-2012 залишилось 21 день 23 години 43 хвилини

середа, 11 січня 2012 р.

Проблема з авторизацією ВКонтакте через OAuth2

Сьогодні стикнувся з помилкою при авторизації по OAuth ВКонтакте:
{"error":"invalid_request","error_description":"redirect_uri is incorrect"}
Виявляється, треба просто вказати правильний домен. Раніше якимось чином все працювало з невірним доменом.


вівторок, 21 червня 2011 р.

ВКонтакте → Авторизація Standalone-додатків використовуючи OAuth 2.0 на прикладі Ruby і Mechanize

Про авторизацію Desktop-додатків ВКонтакте на прикладі Ruby і Mechanize я писав більше року тому. З того часу спливло чимало води:
  • Для авторизації додатків використовується відкритий протокол OAuth 2.0.
  • Запити до API здійснюються без необхідності їх підписувати, завдяки використанню протоколу HTTPS.
Про серверну авторизація ВКонтакте використовуючи OAuth 2.0 я вже писав у цій статті на прикладі Sinatra. У цій статті мова про клієнтську авторизації на прикладі Mechanize.

Поїхали!

четвер, 26 травня 2011 р.

Огляд Padrino і OmniAuth

У цій статті буде показано, як з’єднати модуль автентифікації Access Control, описаний тут, з OmniAuth middleware для Rack.

Система аутентифікації і контролю доступу Padrino забезпечує простий спосіб створювати свої системи аутентифікації. У поєднанні з OmniAuth ви можете легко використовувати її для аутентифікації за допомогою різних методів. Читайте нижче для більш докладної інформації про те, як інтегрувати їх.

У цій статті ми розглянемо дві теми:
  • Інтеграцію Padrino Admin Authentication в усі додатки вашого проекту
  • Створення власних стратегій аутентифікації

На відміну від оригінальної статті, де у якості ORM використовується ActiveRecord, тут ми будемо використовувати DataMapper, про який я писав тут. Можливо вам необхідно познайомитись з фреймворком Padrino, про який я писав тут і тут. І про OmniAuth тут.

Перш ніж ми почнемо, важливо відзначити, що наша вбудована аутентифікація, що базується на ролях, може взаємодіяти з іншими системами. Потрібно лише внести зміни у файли session.rb і account.rb для того щоб додати свій власний код.

Отже, давайте почнемо зі створення проекту використовуючи DataMapper:

пʼятниця, 20 травня 2011 р.

OmniAuth: Зовнішня, проста автентифікація для Rack на прикладі Sinatra і ВКонтакте

В останні один-два роки веб-додатки зазнали радикальних змін. Час, коли кожен сайт представляв собою бункер, який чекає приходу нових користувачів поступово проходить. Я роздратовано зітхаю кожен раз, коли мені доводиться заповнювати чергову реєстраційну форму замість того, щоб скористатися "Connect with Facebook", "Sing in with Twitter" або "Log in with OpenID". Зараз веб-додатки стають все більш відкритими світу. Один з кращих способів збільшення популярності та життєздатності нового сервісу є його доповнення існуючими базами користувачів таких додатків, як: Twitter, Facebook, ВКонтакте, тощо.

Нещодавно я писав про авторизацію додатків ВКонтакте використовуючи відкритий протокол OAuth 2.0. У цій статті мова піде про OmniAuth.

OmniAuth - система аутентифікації заснована на Rack, яка значно спрощує зовнішню аутентифікацію в тому сенсі, що вам немає потреби розбиратися в API провайдерів, а також не вимагає ніякої інформації про те, що буде відбуватися з надіcланими після аутентифікації даними.

Що це означає для вас? Це означає, що ви можете легко реалізувати аутентифікацію в вашому додатку через Twitter, Facebook, LinkedIn, Google, GitHub, ВКонтакте, Mailru і т.д. І потім мати повний контроль над нею.

середа, 13 квітня 2011 р.

Авторизація ВКонтакте використовуючи OAuth 2.0 на прикладі Ruby і Sinatra

Віднедавна для авторизації додатків ВКонтакте використовується відкритий протокол OAuth 2.0. Тепер інтегрувати сайти і клієнтські програми з соціальною мережею стало значно простіше.
На сторінці з документацією нової системи авторизації написано, що підтримуються два типи авторизації: серверна і клієнтська.
У результаті проходження процесу авторизації вам видається ключ доступу access_token, з допомогою якого ви можете виконувати будь-які запити до API ВКонтакте від імені користувача або від імені додатку.
Не дивлячись на новизну протоколу OAuth 2.0, вже зараз на його сайті можна знайти бібліотеки для більшості популярних мов програмування, в тому числі і для Ruby
Крім появи підтримки OAuth у ВКонтакте змінився спосіб взаємодії з API. Тепер всі запити відправляються з безпечного протоколу HTTPS, в результаті чого зникла необхідність підписувати кожен запит.
Я не буду вдаватися у подробиці процесу авторизації. Про це можна почитати у документації ВКонтакте.
Нижченаведений код показує наскільки легко використовувати API ВКонтакте з OAuth2 gem в Ruby.

середа, 28 квітня 2010 р.

ВКонтакте → Авторизація Desktop-додатків на прикладі Ruby і Mechanize

Увага! Дана версія документації є застарілою. Замість неї я рекомендую прочитати статтю ВКонтакте → Авторизація Standalone-додатків використовуючи OAuth 2.0 на прикладі Ruby і Mechanize

Нещодавно розробники соціальної мережі ВКонтакте повідомити про запуск можливості використання VK API для standalone-додатків. Я ж вирішив експериментально перевірити цю нову можливість у зв'язці з мовою Ruby.

Використані джерела:

Авторизація Desktop-додатків
Desktop-додатки на відміну від звичайних програм ВКонтакте запускаються у вигляді звичайних програм на пристрої користувача, яким може бути комп'ютер, комунікатор або смартфон. Наприклад, це може бути додаток на платформі Adobe AIR або додаток для iPhone, написане на Objective-C.

Почав писати обгортку до цього на Ruby. І відразу ж засмутився - авторизація на даний момент через одне місце. Потрібен компонент браузера з підтримкою JavaScript. Насправді я уявлення не маю як таке реалізувати на Ruby. Доведеться вручну вивчати що і куди посилати. Але чому б не зробити метод у який висилається логін-пароль? І просто отримувати ID сесії.
Маємо те, що маємо. Обійдемося поки цим. А в майбутньому, надіюся виправлять.
Для початку необхідно створити новий або взяти вже існуючий додаток.

четвер, 4 лютого 2010 р.

Як дізнатися, хто Вас додав в закладки на ВКонтакте?

Как узнать кто добавил в закладки вконтакте?

Вас напевно завжди мучила цікавість? І, напевно, вам завжди хотілося дізнатися, у кого ж ви перебуваєте в закладках, хто вважає вас цікавим? Ви можете легко про це дізнатися. Все що потрібно для цієї інструкції - це інтерпретатор Ruby і бібліотека WWW::Mechanize

середа, 14 жовтня 2009 р.

vk.com. Частина 7

У цьому дописі мова знову піде про ВКонтакте і WWW::Mechanize. Хоч він і йде під номером сім, він не є продовженням попередніх частинами, хоча для повного розуміння про далі буде йти мова, бажано ознайомитися з ними. З них ви можете дізнатися, як робити наступні речі ВКонтакте:

  • Отримання новин профілю (кількості нових повідомлень, фотографій, відео, друзів, груп).

  • Отримання списку друзів

  • Отримання приватних повідомлень

  • Написання приватних повідомлень



Я вже писав про те, що домен VK.COM перейшов під контроль соціальної мережі ВКонтакте. Майже з тих самих пір авторизація користувачів на сайті vkontakte.ru відбувається через редірект login.vk.com. Це викликає незручність при авторизації за допомогою WWW::Mechanize.

require 'mechanize'
require 'json'

class Vkontakte
def initialize
@ua = WWW::Mechanize.new{|agent|
agent.user_agent_alias = 'Linux Mozilla'
agent.follow_meta_refresh = true
}
end

# Authorisation by submitting email and password (Login)
#
def login_force(uid, email, pass)
url = "http://login.vk.com/?act=login"
page = @ua.post(url, {'email' => email, 'pass' => pass, 'expire' => '1', 'vk' => 1})
s = page.body.match(/'s' value='(.+?)'/)[1]
@ua.post('http://vkontakte.ru/login.php?op=slogin&redirect=1', {'s' => s})
user_page = @ua.get('http://vkontakte.ru/profile.php')
end

end

if __FILE__ == $0
id = "xxxxxxxx"
email = "user@example.com"
pass = "your_password"

vkontakte_agent = Vkontakte.new
vkontakte_agent.login_force(id, email, pass)

end


Далі можна продовжувати роботу з ВКонтакте як звичайно.

субота, 12 вересня 2009 р.

Keyword: login.vk.com/?act=login



Судячи з активності, або народ переживає, або щось не так...
Доменне ім’я vk.com віднедавна належить мережі "В контакте". VK на пути к мировому господству. А API нормальне не можуть надати, так то.

вівторок, 21 липня 2009 р.

Mechanize + Cookie + вКонтакте. Частина 6



Куки(від англ. Cookie - печиво) - фрагмент даних, який створюється веб-сервером і зберігається на комп'ютері користувача у вигляді файлу, який веб-клієнт(зазвичай веб-браузер) кожен раз пересилає веб-серверу у HTTP-запиті при спробі відкрити сторінку відповідного сайту. Застосовується для збереження даних на стороні користувача, на практиці зазвичай використовується для:

  • автентифікації користувача;

  • зберігання персональних даних і налаштувань користувача;

  • відслідковування стану сесії доступу користувача;

  • ведення статистики про користувачів.



Бібліотека WWW::Mechanize надає зручний інтерфей для роботи з куками - WWW::Mechanize::CookieJar. Цей клас використовується для керування куками, які були повернуті з якого-небудь конкретного сайту. Крім того дозволяє зберігати куки до файлу, з можливістю використовувати його пізніше(наприклад, для автентифікації користувача на сайті без необхідності вводу логіна і пароля). Доступні наступні формати для зберігання/завантаження куки: :yaml <- YAML структура і :cookiestxt <- Mozilla у форматі cookies.txt.


Повернемося до попередньої статті і додамо можливість авторизації за допомогою пересилання куки вебсерверу.
Авторизація здійснюється через надсилання куки 'remixpassword'. Значення 'remixpassword', встановлюється в результаті успішної авторизації, і може бути використане для продовження ідентифікатора сесії('sid').
Цей метод можна використати і у UserAPI при запиті до http://login.userapi.com/auth?login=auto&site=2.

Тут я не буду приводити повний лістинг. А лише доповню код з попередньої статті.
Для початку потрібно авторизуватися на сайті ВКонтакте і записати куки у файл на диску. Для цього створимо новий метод save_cookie().
def save_cookie(cookie_file)
@a.cookie_jar.save_as(cookie_file, format = :cookiestxt)
end

Якщо авторизація пройшла успішно, записуємо куки у файл cookie.txt

if login_force(id, email, pass)
puts "Successfully Authentication"
save_cookie('cookie.txt')
else
puts "Authentication Error"
end


Далі ми будемо авторизовуватись за допомогою цією куки. Створимо метод login_auto()

def login_auto(uid, cookie_file)
@a.cookie_jar.load(cookie_file, format = :cookiestxt)
login_page = @a.get('http://vkontakte.ru/')
return /http:\/\/vkontakte\.ru\/id(\d+)/ === login_page.uri.to_s ? ($1 == uid ? true : false) : false
end


Надалі у нас нема необхідності використовувати метод login_force(). Замість нього використовуємо login_auto()

if login_auto(id, 'cookie.txt')
puts "Successfully Authentication"
else
puts "Authentication Error"
end


Якщо комусь цікаво про плюси авторизації за допомогою куки(в т.ч. і на сайті ВКонтакте), залишайте коментарі.

пʼятниця, 10 липня 2009 р.

Mechanize + Nokogiri + вКонтакте. Частина 5


Ніхто не помітив зовнішніх змін. Положення тіла пацієнта вКонтакте на операційному столі залишалось незмінним. Але мушу повідомити неприємну новину: ідентифіковано мутації. Тому всі попередні дослідження [1][2][3][4] вважаються недійсними. Нічого... не треба падати духом.
Їжачки плакали і кололись, але продовжували кохатися з кактусами! ©

Nokogiri - це парсер HTML, XML, SAX. Серед його численних можливостей можна виділити можливість використання XPath(XML Path Language) і CSS3 селекторів для пошуку.
Крім того Nokogiri має сумісний з Hpricot синтаксис XPath та CSS.
На даний час Nokogiri найшвидший парсер XML для Ruby.
Mechanize для синтаксичного розбору html використовує саме Nokogiri.

Приклад використання:

Підключення необхідних бібліотек
require 'nokogiri'
require 'open-uri'

Завантаження HTML сторінки, використовуючи open-uri, який йде з Ruby
doc = Nokogiri::HTML(open('http://www.google.com/search?q=ruby-ua'))

Пошук вузлів за допомогою CSS3 селекторів
doc.css('h3.r a.l').each{|link| puts link.content}

Пошук вузлів за допомогою XPath
doc.xpath('//h3/a[@class="l"]').each {|link| puts link.content}


Автор рекомендує використовувати XPath селектори для вищої швидкодії - пошук CSS швидкий ніж у Hpricot, але не такий швидкий.
Nokogiri::XML::Node#xpath(*paths) - функція пошук вузлів(nodes) для XPath шляхів(paths). Шлях повинен бути одним або декількома XPath запитами(queries).
Цікавоє можливістю є задання власних функцій XPath із використанням регекспів(regexp). Для цього потрібно створити класс і застосувати функцію # яку хочете визначити. Наприклад:

node.xpath('.//tr[mess(., "mess\d+")]', Class.new {
def mess node_set, regex
node_set.find_all { |node| node['id'] =~ /#{regex}/ }
end
}.new)


Така функція знайде всі вузли виду:
<tr id="mess127">[...]</tr>
<tr id="mess128">[...]</tr>
<tr id="mess129">[...]</tr>


вКонтакте!?
У зв'язку зі змінами на сайті vkontakte.ru мої попередні дописи про вконтакте втратили свою актуальність. Не знаю скільки часу буде працездатним цей код. Але суть в іншому: показати принципи роботи з Mechanize і Nokogiri на реальному прикладі.
Що ж робить нищеприведений код?

  • Авторизація через надсилання email-адреси та пароля користувача; (login_force)

  • Отримання останніх приватних повідомлень; (get_messages)


# -*- encoding: utf-8 -*-
require 'mechanize' # recommended 0.9.2

@a = WWW::Mechanize.new{|agent|
agent.user_agent_alias = 'Linux Konqueror'
agent.follow_meta_refresh = true
}

# Authorisation by submitting email and password (Login)
#
def login_force(uid, email, pass)
login_page = @a.get('http://vkontakte.ru/login.php')
login_form = login_page.form_with(:name => "login")
login_form.email = email
login_form.pass = pass
user_page = login_form.submit
return /http:\/\/vkontakte\.ru\/id(\d+)/ === user_page.uri.to_s ? ($1 == uid ? true : false) : false
end

# Getting private messages list for current user
#
# Structure of each entry of resulting array
# [0] - message from
# [1] - message date
# [2] - message title
# [3] - message_body
#
def get_messages
url = 'http://vkontakte.ru/mail.php'
messages_page = @a.get(url)
node = Nokogiri::HTML(messages_page.body)
message = node.xpath('.//tr[mess(., "mess\d+")]', Class.new {
def mess node_set, regex
node_set.find_all { |node| node['id'] =~ /#{regex}/ }
end
}.new)
message_from = message.xpath('//td[@class="messageFrom"]/div[@class="name"]/a').map {|link| /\/id(\d+)/.match(link['href'])[1]}
message_date = message.xpath('//td[@class="messageFrom"]/div[@class="date"]').map {|link| link.content}
message_title = message.xpath('//a[@class="new messageSubject"]/span').map {|link| link.content}
message_body = message.xpath('//a[@class="new messageBody"]').map {|link| link.content}
messages = Array.new
messages = [message_from, message_date, message_title, message_body].transpose
return messages
end

id = "12345678"
email = "username@example.com"
pass = "secret"

if login_force(id, email, pass)
puts "Successfully Authentication"
get_messages.each {|message|
puts "[#{message[1]}]: #{message[0]}"
puts message[2]
puts message[3]
puts "==="
}
else
puts "Authentication Error"
end

понеділок, 11 травня 2009 р.

Curb (Ruby + cURL) + вКонтакте. Частина 4



Сьогодні продовжимо копатися у тенетах...
На операційному столі і досі лежить пацієнт вКонтакте. Хтось запевняє, що він живіший за всіх живих Операцією керує доктор Ruby. Ця людина не потребує представлення. І сьогодні його асистентом є відомий у вузьких колах майстер ножа і скальпеля, хірург - cURL. Прошу любіть і жаловать! :) Бурні овації в залі.

cURL - це програма командного рядка для передачі файлів з синтаксом URL, яка підтримує FTP, FTPS, HTTP, HTTPS, TFTP, SCP, SFTP, Telnet, DICT, Файли: URL і LDAP. cURL підтримує сертифікати HTTPS, методи HTTP POST, HTTP PUT, завантаження на FTP, Kerberos, завантаження через форми HTTP, проксі, файли cookie, перевірку автентичності «ім'я користувача + пароль» (базову, дайджест, NTLM і Negotiate для HTTP, а також kerberos4 для FTP), поновлення передачі файлів, тунелювання через проксі HTTP та багато інших функцій. cURL - це вільне програмне забезпечення, що розповсюджується під ліцензією MIT.

Головна мета використання cURL полягає в тому, щоб автоматизувати передачу файлів або послідовність таких операцій. Наприклад, це хороший засіб для моделювання дій користувача у веб-оглядачі.

Libcurl - це API інтерфейс, який можна включити в свої програми; cURL діє як автономна обгортка для бібліотеки libcurl. libcurl використовується, щоб забезпечити можливість передачі URL численним додаткам (як відкритим, так і комерційних). Для libcurl є більше 30 різних прив'язок до мов програмування. В тому числі і для Ruby: Curb та curl-multi.

Сьогодні розглянемо роботу з libcurl на Ruby 1.8, за допомогою Curb. З сторінки проекту "Curb is a work-in-progress, and currently only supports libcurl‘s ‘easy’ mode". Вже по традиції, на прикладі сайту вКонтакте.
Але для початку потрібно встановити необхідні бібліотеки.
$ sudo apt-get install libcurl4-gnutls-dev
$ sudo gem1.8 install curb


Сьогодні наша задача полягатиме у написанні простого парсера на Рубі, який перевіряє нову інформацію з особистої сторінки вКонтакте: кількість повідомлень, запрошень у групи, нових фотографіях і відео, на яких вас відзначили, коментарі в замітках, запрошень на зустрічі, відповідей на пропозиції та питання, анонімних думок. Для того щоб скрипт працював у вас, достатньо змінити рядок
body = getdata(mid = '********', email = 'user@example.com', pass = '*********')

де mid - ваш числовий ID наприклад 12227146 (http://vkontakte.ru/id12227146), email - ваш логін, і pass - ваш пароль.
Наразі скрипт праює тільки з версією Ruby 1.8. Скомпілювати Curb для 1.9 мені не вдалось.

# -*- coding: utf-8 -*-

# ruby1.8
require 'rubygems'
require 'curb'
require 'md5'
require 'iconv'

def trymatch(str, regex)
if str.match(regex) == nil
return '0'
end
str.match(regex)[2]
end

def filter(data, label, tool)
# <li id='myfriends'><a href='/friend.php?24072'>My Friends</a></li>
# <li><a href='/mail.php?id=32576819&24072'>My Messages (<b>1</b>)</a></li>
regex = /<a href=\'\/#{tool}.php?([\w\d\s\?\'&=>]*)\'>[\w\s]*\(<b>(\d+)<\/b>\)<\/a>/m
rez = trymatch(data, regex)
label + ": " + rez
end

def getdata(mid, email, pass)
user = {'mid' => mid, 'email' => email, 'pass' => MD5.md5(pass)}
curl = Curl::Easy.new("http://vkontakte.ru/id#{mid}")
curl.headers = {"User-Agent" => "Opera/10.00 (X11; Linux i686; U; uk) Presto/2.2.1",
"Cookie" => "remixlang=3; remixchk=5; remixmid=#{user['mid']}; remixemail=#{user['email']}; remixpass=#{user['pass']}; remixautobookmark=8",
"Referer" => "http://vkontakte.ru/"}
curl.follow_location = true
curl.perform
#return '0'
body = curl.unescape curl.body_str
coder = Iconv.new("UTF-8","WINDOWS-1251")
body = coder.iconv(body)
return body
end

body = getdata(mid = '********', email = 'user@example.com', pass = '*********')

puts filter(body,'Friends','friend')
puts filter(body,'Photos','photos')
puts filter(body,'Videos','video')
puts filter(body,'Messages','mail')
puts filter(body,'Notes','notes')
puts filter(body,'Groups','groups')
puts filter(body,'Events','events')
puts filter(body,'Matches','matches')
puts filter(body,'Opinions','opinions')
puts filter(body,'Questions','questions')
puts filter(body,'Opinions','opinions')


Список посилань:

четвер, 12 березня 2009 р.

Ruby + User API Vkontakte. Частина 3

28 жовтня 2008 Павло Дуров заявив про відкриття нового проекту: User API.
Сервіс призначений для швидкої побудови соціальної мережі або будь-яких інших клієнтів (цього на сторінці не заявлено).
Нові проекти будуть використовувати дані мережі ВКонтакте (користувачі, фото, т.п.).
Докладна інформація і документація по User API ВКонтакте доступна на англійською і російською мовами.
API побудований на обміні даними між клієнтом і сервером у вигляді HTTP-запитів, і відповіді від сервера клієнту у вигляді JSON-масиву в кодуванні UTF-8. Підтримується пакування GZIP. Передача даних клієнту, як правило, передбачає авторизацію клієнта в системі за допомогою передачі серверу ідентифікатора сесії('SiD') при будь-якому запиті даних.

Від сухої теорії до практики.

Напишемо простий скрипт:

  • Авторизація через надсилання email-адреси та пароля користувача;

  • Отримання інформації профілю;

  • Отримання списку друзів користувача, які в даний момент онлайн на сайті.


Будемо використовувати вже знайомі з мої попередніх постів бібліотеки WWW::Mechanize і JSON.
Створимо клас VkontakteAPI і методи login, get_user_page, get_friends_online_list.

Невеликий нюанс. Після успішної авторизації, на запит "http://userapi.com/data?act=profile&id=#{id}&sid=#{sid}", сервер повертає JSON на кшталт
[...]
{0: "xxxxxxxx_", 1: xxxxxxxx, 2: 1, 3: "First Last", 4: null, 5: "", "ts": 346000002}
[...]

Згідно специфікіції: строка - це набір символів Unicode, взятих у подвійні лапки А тут - без повдійних лапок. Парсер Ruby JSON видає помилку. Використаємо хак для виправлення цього у функції hack_json.

# -*- encoding: utf-8 -*-
#
# For more documentation see http://userapi.com

require 'json'
require 'mechanize'

class VkontakteAPI
def initialize
@sid = nil
@id = nil
@agent = WWW::Mechanize.new{|agent|
agent.user_agent_alias = 'Linux Konqueror'
}
end

# Authorisation by submitting email and password (Login)
#
def login(email, pass)
url = "http://login.userapi.com/auth?login=force&site=2&email=#{email}&pass=#{pass}"
login_page = @agent.get(url)
if !@agent.cookies.nil?
@id = /remixmid=(\d+)/.match(@agent.cookies[0].to_s)[1]
@sid = /.*;sid=(\w*)/.match(login_page.uri.to_s)[1]
return true
else
return false
end
end

# Getting user's profile information
#
def get_user_page(id = @id)
url = "http://userapi.com/data?act=profile&id=#{id}&sid=#{@sid}"
user_info_page = @agent.get(url)
JSON.parse(hack_json(user_info_page.body))
end

# List of online friends of a user
#
def get_friends_online_list(id = @id, from=0, to=5000)
url = "http://userapi.com/data?act=friends_online&from=#{from}&to=#{to}&id=#{id}&sid=#{@sid}"
friends_list_page = @agent.get(url)
JSON.parse(friends_list_page.body)
end

# little User API JSON hack :)
# Name property must be a String wrapped in double quotes
#
def hack_json(json_s)
json_s.gsub(/(\d+):/, '"\1":')
end

private :hack_json

end

if __FILE__ == $0
email = ARGV[0]
pass = ARGV[1]

vk = VkontakteAPI.new
if vk.login(email, pass)
puts vk.get_user_page
puts "Online friends:"
vk.get_friends_online_list.each do|friend|
puts "#{friend[0]}: #{friend[1]}"
end
else
"Error"
end
end

понеділок, 9 березня 2009 р.

Eval і Ruby

У Ruby (та інших скриптових мовах) є метод eval, який отримує рядок і виконує цей рядок в поточному контексті
так (майже так), як ніби він був написана програмістом в місці виклику eval.
Власне, засоби, подібні eval, є і в компільованих мовах програмування.

Приклад для Ruby:
eval("puts 'Hello World'")

Вивід:
Hello World


Повертаючись до попереднього посту зробимо деякі зміни у коді.
Маємо метод, який повертає кількість нових повідомлень.
def new_messages
get_feed['messages']['count']
end


Аналогічно можна написати для фотографій(photos) і відео(videos)...
Керуючись філософською думкою DRY підемо іншим шляхом.
Замість того щоб писати 9 майже однакових методів, застосуємо силу eval.
[:friends, :messages, :events, :groups, :photos, :videos, :notes, :opinions, :offers].each do |type|
eval(<<-eomethod)
def new_#{type}
get_feed['#{type}']['count']
end
eomethod
end

Таким чином ми згенерували 9 нових методів для класу Vkontakte.

пʼятниця, 6 березня 2009 р.

Mechanize + вКонтакте. Частина 2

Тихо і непомітно вийшов mechanize 0.9.2 у якому виправлений неприємний баг з Iconv.

Продовжим розбиратися з vkontakte.ru і бібліотекою mechanize. У попередньому дописі ми парсили веб-сторінку
і зчитували кількість нових повідомлень і фотографій. Така реалізація є незручною з багатьох причин, хоча і має право на існування. Розробники сервісу надали зручнішу річ для перегляду новин про профіль(http://vkontakte.ru/feed.php і http://vkontakte.ru/feed2.php).
http://vkontakte.ru/feed.php при відкритті окремо видає щось типу:
{"user": {"id": номер}, "friends": {"count": 0}, "messages": {"count": 0}, "events": {"count": 0}, "groups": {"count": 0}, "photos": {"count": 0}, "videos": {"count": 6}, "notes": {"count": 0}, "opinions": {"count": 0}, "offers": {"count": 0}}


Мова піде про JSON.

Wikipedia каже про нього наступне:

JSON (англ. JavaScript Object Notation, укр. об'єктний запис JavaScript, вимовляється джейсон) — це легкий формат обміну даними між комп'ютерами. JSON базується на тексті, і може бути з легкістю прочитаним людиною. Формат дозволяє описувати об'єкти та інші структури даних. Цей формат головним чином використовується для передачі структурованої інформації через мережу (завдяки процесу, що називають серіалізацією).

JSON знайшов своє головне призначення у написанні веб-програм, а саме при використанні технології Ajax. JSON виступає як заміна XML під час асинхронної передачі структурованої інформації між клієнтом та сервером. При цьому перевагою JSON перед XML є те, що він займає менше місця і прямо інтерпретується за допомогою JavaScript в об'єкти.



JSON - реалізації JSON для Ruby.
В Ruby 1.9.1 JSON входить в офіційне дерево вихідних кодів.

Нище вдосконалений скрипт із моєї попередньої статті.
Тепер крім зчитування кількості нових повідомлень, він ще зчитує кількість друзів, та друзів онлайн.
Хоча Mechanize і є емулятором веб-браузера, він не вміє(і наврядчи колись навчиться) виконувати JavaScript. А саме ним формується список друзів на сторінці http://vkontakte.ru/friend.php. У функціях friends_list і online_friends_list ми просто парсимо JavaScript на HTML-сторінці.
<script>friendsInfo [...] </script>


Скрипт протестований на Ruby 1.9.1 і Mechanize 0.9.2.
# -*- encoding: utf-8 -*-

require "json"
require "rubygems"
require "mechanize"

class Vkontakte

def initialize
@login = false
@a = WWW::Mechanize.new {|agent|
agent.user_agent_alias = 'Linux Konqueror' # WWW::Mechanize::AGENT_ALIASES
agent.follow_meta_refresh = true # VKontakte refresh after login
}
end

def online?; @online; end

# Sing in http://vkontakte.ru/
# Return false if error
#
def login!(email, pass)
@a.get('http://vkontakte.ru/login.php') do |login_page|
login_page.form_with(:name => 'login') do |form|
form.email = email
form.pass = pass
end.submit
if get_feed['user']['id'] == -1
@online = false
return false
else
@online = true
return true
end
end
end

def logout!
@a.get('http://vkontakte.ru/login.php?op=logout') do |page|
if get_feed['user']['id'] == -1
@online = false
return true
else
return false
end
end
end

# Return Hash of friend's uid => [first_name, last_name]
#
def friends_list
@a.get('http://vkontakte.ru/friend.php') do |friends_page|
friends = Hash.new
friends_page.body.scan(/\[(\d+?), \{f:'(.+?)', l:'(.+?)'\},\{p:.*?\}\]/mi).map{|item| friends[item[0]]=[item[1], item[2]]}
return friends
end
end

def online_friends_list
@a.get('http://vkontakte.ru/friend.php?act=online') do |friends_page|
friends = Hash.new
friends_page.body.scan(/\[(\d+?), \{f:'(.+?)', l:'(.+?)'\},\{p:.*?\}\]/mi).map{|item| friends[item[0]]=[item[1], item[2]]}
return friends
end
end

# Get JSON page and convert it to Hash object
#
def get_feed
@a.get('http://vkontakte.ru/feed2.php?mask=ufmepvnoq') do |feed_page|
return JSON::parse(feed_page.body)
end
end

def new_messages
get_feed['messages']['count']
end

private :get_feed

end


vk = Vkontakte.new
vk.login!(ARGV[0], ARGV[1])
if vk.online?
flist = vk.friends_list
oflist = vk.online_friends_list
puts "Friends: #{flist.size}"
puts "Online friends:"
oflist.each{|fid, fname| puts "#{fid}: #{fname[0]} #{fname[1]}"}
puts "New messages: #{vk.new_messages}"
vk.logout! ? "Good bye!" : "Ooops..."
else
puts "Such an e-mail address is not registered or an incorrect password is entered"
end


субота, 17 січня 2009 р.

Mechanize + вКонтакте

Цей допис несе навчально-практичний характер. На прикладі бібліотеки Mechanize я продемонструю як просто можна серфити веб-сторінками.
наш простий скрипт буде виконувати наступні дії:

  • Авторизація на сайті ВКонтакте

  • Зчитування кількості нових повідомлень і фотографій


І все це без використання веб-броузера.
Далі трохи теорії.

Mechanize використовується для автоматизації взаємодії з веб-вузлами. Mechanize автоматично запам'ятовує і відсилає куки(cookies), слідує за перенаправленнями(redirects), може переходити по лінках. Може використовуватись для заповнення форм. Крім того Mechanize тримає в історії список сайтів, які ви відвідали.
А для синтаксичного розбору html використовує nokogiri.

А тепер власне сам скрипт. У якості параметрів він приймає е-мейл і пароль. На виході - кількість нових фотографій і повідомлень. Крім того у скрипті передбачена реакція на невірний логін/пароль.
Це лише невелий приклад і можливість розширення обмежується тільки вашою фантазією.

require "rubygems"                                                          
require "mechanize"

$KCODE = "UTF8"

a = WWW::Mechanize.new {|agent|
# WWW::Mechanize::AGENT_ALIASES
agent.user_agent_alias = 'Linux Konqueror'
# VKontakte refresh after login
agent.follow_meta_refresh = true
}

a.get('http://vkontakte.ru/') do |home_page|
# home_page.links.each{|link| puts link.text}
# home_page.forms.each{|form| puts form.name}
singin_page = a.click(home_page.links_with(:text => 'Login').first)
my_page = singin_page.form_with(:name => 'login') do |form|
form.email = ARGV[0]
form.pass = ARGV[1]
end.submit
if my_page.title == 'VKontakte | Login'
puts "Such an e-mail address is not registered or an incorrect password is entered"
end
#pp my_page

# <div id="sideBar">
# <ol id='nav'>
# <li><a href='mail.php?id=13327146&41867'>My Messages</a></li>
# </ol>
# </div>
#
# Mix and match
messages = my_page.search('div.ol.li.a', '//div[@id="sideBar"]/ol[@id="nav"]/li/a').each do |link|
case link.content
when /My Messages/
messages = link.content.match(/^(My Messages)($)?( \((\d+)\)$)?/)[4] || 0
puts "Messages: #{messages}"
when /My Photos/
photos = link.content.match(/^(My Photos)($)?( \((\d+)\)$)?/)[4] || 0
puts "Photos: #{photos}"
end
end
end