пʼятницю, 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


3 коментарі:

Волошин Руслан сказав...

И как дальше ты будешь использовать эти данные???

Anton Maminov сказав...

Используя для получения нотификациы о поступлении новых сообщений.
Именно эти уже никак. Структура сайта часто меняется :(.

burgua сказав...

С mechanize красивее чем с curb, одобряю статью )