Настало время писать на Руби что-то пригодное для использования ;) Сегодня мы научимся выдирать нужную нам информацию из web-страниц с помощью Руби на примере Хабра. Начнем с кармы.
Давайте каждый откроет свою персональный Хаброцентр (ну или чужой, если все еще не обзавелись инвайтом ;) с адресом вида %username.habrahabr.ru. Наша задача – извлечь из полутысячи строк HTML-кода значение нашей кармы. Предполагаем, что для этого нам необходимо сохранить код страницы в файл, открыть и прочитать его и, используя регулярные выражения, получить необходимую информацию.
Библиотека
open сохранит страницу в Tempfile, откуда мы прочитаем содержимое в строку text.
Для того, чтобы выловить карму, составим регулярное выражение вида
И вот несложное регулярное выражение готово:
Используем
Готово! Теперь вы можете добавить возможность вводить произвольный username, вывод хабрасилы, а также оформить все в ООП: выделить методы и классы.
Достаточно удобно было бы парсить HTML, используя его же теги – ведь они замечательно структурируют информацию. В нашем примере достаточно узнать текст, заключенный в span, который в свою очередь заключен в span класса mark – и все, никаких сложных регулярных выражений. Однако тут есть одна нестыковка – не все документы имеют действительно валидный HTML, например, незакрытые и пропущенные теги. Чтобы решить проблему, достаточно перевести HTML в XML, четко структурированный формат, парсинг которого – обычная задача.
Устанавливаем:
На сегодняшний день большая часть данных находится в “глубоком Вебе” – в базах данных, доступных через формы. Информация отсутствует в статичных страницах и генерируется налету, либо доступна только после только регистрации и аутентификации. В этот момент в игру вступает
Считать карму мы уже научились, а что делать, если мы хотим узнать, например, количество непрочитанных личных сообщений на хабре? Нам нужно пройти аутентификацию, получить cookies и только тогда выдернуть кол-во сообщений. Попробуем решить проблему максимально удобным способом!
Как всегда начнем с установки джема:
Таким образом Mechanize позволяет нам заполнять формы, нажимать кнопки, ходить по ссылкам, имитируя браузер. Вместе с hpricot — опасная смесь ;)
Собственно, еще немного инфы — дальше будем смотреть другие библиотечки, практиковать их полезное использование. Жду отзывов!
open-uri
Давайте каждый откроет свою персональный Хаброцентр (ну или чужой, если все еще не обзавелись инвайтом ;) с адресом вида %username.habrahabr.ru. Наша задача – извлечь из полутысячи строк HTML-кода значение нашей кармы. Предполагаем, что для этого нам необходимо сохранить код страницы в файл, открыть и прочитать его и, используя регулярные выражения, получить необходимую информацию.
Библиотека
open-uri
сделает первую часть работы за нас. После включения ее в программу становится доступен метод open, который позволяет открывать как локальные файлы, так и URL:require 'open-uri'
url = 'http://maxelc.habrahabr.ru/'
page = open(url)
text = page.read
open сохранит страницу в Tempfile, откуда мы прочитаем содержимое в строку text.
Используем регулярные выражения
Для того, чтобы выловить карму, составим регулярное выражение вида
/НАЧАЛО(.*)КОНЕЦ/
. Посмотрим на нужный нам кусок HTML-кода:<span class="mark"><span>68,25</span><strong class="sign"></strong></span>
И вот несложное регулярное выражение готово:
%r{mark"><span>(.*)</span><strong class="sign">}m
Используем
%r{}
, чтобы забыть о правильности слэшей (очень удобно, в частности с HTML), m
в конце строки говорит Руби искать совпадения на нескольких строках (в нашем случае это неважно, однако, опять же, весьма полезно в работе с HTML). Для поиска совпадений в строке будем использовать метод scan
:karma = text.scan(%r{mark"><span>(.*)</span><strong class="sign">})
puts "Karma = #{karma}"
Готово! Теперь вы можете добавить возможность вводить произвольный username, вывод хабрасилы, а также оформить все в ООП: выделить методы и классы.
hpricot
Достаточно удобно было бы парсить HTML, используя его же теги – ведь они замечательно структурируют информацию. В нашем примере достаточно узнать текст, заключенный в span, который в свою очередь заключен в span класса mark – и все, никаких сложных регулярных выражений. Однако тут есть одна нестыковка – не все документы имеют действительно валидный HTML, например, незакрытые и пропущенные теги. Чтобы решить проблему, достаточно перевести HTML в XML, четко структурированный формат, парсинг которого – обычная задача.
Hpricot
– быстрый и удобный, основанный на С, HTML парсер, который как раз так и действует. Для парсинга XML используются библиотеки JQuery
.Устанавливаем:
gem install hpricot
. Начинаем кодить. Включаем hpricot
в программу и загружаем URL, находим нужный элемент, заворачивая сразу все в ООП:class Karma
require 'rubygems'
require 'hpricot'
require 'open-uri'
def initialize(name)
@url = "http:\/\/" + name + ".habrahabr.ru\/";
@hp = Hpricot(open(@url))
end
def get
(@hp/"span.mark/span").inner_text
end
end
karma = Karma.new('maxelc')
puts "Karma = #{karma.get}"
Hpricot(open())
как раз преобразует HTML в XML и создает методы для переменной. @hp/"span.mark"
– это шорткат от @hp.search("//span[@class='mark']")
, означающий “ищи тэг <span class=’mark’>”
(search в качестве параметра принимает выражение XPath
или CSS
). Метод inner_html
получает содержание элемента (в случае HTML то, что заключено в тэги). Изменяя запрос, мы можем уходить во вложенные тэги, что мы и сделали: @hp/"span.mark/span”
.WWW::Mechanize
На сегодняшний день большая часть данных находится в “глубоком Вебе” – в базах данных, доступных через формы. Информация отсутствует в статичных страницах и генерируется налету, либо доступна только после только регистрации и аутентификации. В этот момент в игру вступает
WWW::Mechanize
.Считать карму мы уже научились, а что делать, если мы хотим узнать, например, количество непрочитанных личных сообщений на хабре? Нам нужно пройти аутентификацию, получить cookies и только тогда выдернуть кол-во сообщений. Попробуем решить проблему максимально удобным способом!
Как всегда начнем с установки джема:
gem install mechanize
. Пишем код:require 'rubygems'
require 'mechanize'
require 'hpricot'
agent = WWW::Mechanize.new # содержит инфу о куки, сессиях и др.
page = agent.get 'http://habrahabr.ru/login/'
form = page.forms.first # первая форма, которая встретится на странице
form.login = 'MaxElc' # см. атрибут name в HTML
form.password = '****'
page = agent.submit form # отправляем
a = agent.get('http://habrahabr.ru/').search(".//a[@href='http://maxelc.habrahabr.ru/mail/']").inner_text # сочетаем с hpricot
puts "У вас #{a}!"
Таким образом Mechanize позволяет нам заполнять формы, нажимать кнопки, ходить по ссылкам, имитируя браузер. Вместе с hpricot — опасная смесь ;)
Эпилог
Собственно, еще немного инфы — дальше будем смотреть другие библиотечки, практиковать их полезное использование. Жду отзывов!