субота, 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

3 коментарі:

Анонім сказав...

Рубі ще якийсь сирий, разом зі своїми гемами і відсутністю нормального цпану і доків, особливо до механайзу - там майже нічого не прописано, навіть не можна тип інпуту дізнатись :(

Паштет сказав...

Для таких целей, думаю проще юзать API Vkontakt (http://userapi.com/?act=doc), нежели парсить сам сайт.
Но, для других целей, например отсылать инвайты в группу, без этого не обойтись...

_linux_ сказав...

@Паштет
Не все возможности сайта доступны через API. Используя API иногда банят аккаунт. Неприятно.
Ruby + User API Vkontakte. Частина 3