Разбор HTML-таблицы с использованием Hpricot (Ruby) - PullRequest
0 голосов
/ 20 марта 2009

Я пытаюсь разобрать таблицу HTML, используя Hpricot, но застрял, не могу выбрать элемент таблицы на странице, которая имеет указанный идентификатор.

Вот мой рубиновый код: -

require 'rubygems'
require 'mechanize'
require 'hpricot'

agent = WWW::Mechanize.new

page = agent.get('http://www.indiapost.gov.in/pin/pinsearch.aspx')

form = page.forms.find {|f| f.name == 'form1'}
form.fields.find {|f| f.name == 'ddl_state'}.options[1].select
page = agent.submit(form, form.buttons[2])

doc = Hpricot(page.body)

puts doc.to_html # Here the doc contains the full HTML page

puts doc.search("//table[@id='gvw_offices']").first # This is NIL

Может кто-нибудь помочь мне определить, что с этим не так.

Ответы [ 2 ]

1 голос
/ 03 апреля 2009

Обратите внимание, что Mechanize больше не использует Hpricot (он использует Nokogiri) по умолчанию в более поздних версиях (0.9.0), и вы должны явно указать Hpricot, чтобы продолжить использовать с:

  WWW::Mechanize.html_parser = Hpricot

Точно так же, без кавычек или чего-то другого в Hpricot - возможно, есть модуль, который вы можете указать для Hpricot, потому что он не будет работать, если вы поместите этот оператор в собственное объявление модуля. Вот лучший способ сделать это на вершине своего класса (до открытия модуля или класса)

require 'mechanize'
require 'hpricot'

# Later versions of Mechanize no longer use Hpricot by default
# but have an attribute we can set to use it
begin
  WWW::Mechanize.html_parser = Hpricot
rescue NoMethodError
  # must be using an older version of Mechanize that doesn't
  # have the html_parser attribute - just ignore it since 
  # this older version will use Hpricot anyway
end

Используя спасательный блок, вы гарантируете, что, если у них есть более старая версия механизации, он не помешает несуществующему атрибуту html_parser. (В противном случае вам нужно сделать свой код зависимым от последней версии Mechanize)

Также в последней версии WWW :: Mechanize :: List устарел. Не спрашивайте меня почему, потому что это полностью нарушает обратную совместимость для операторов типа

page.forms.name('form1').first

, который раньше был обычной идиомой, которая работала, потому что формы Page # возвращали механизированный List, у которого был метод "name". Теперь он возвращает простой массив форм.

Я нашел это сложным путем, но ваше использование будет работать, потому что вы используете find, который является методом массива.

Но лучший способ найти первую форму с заданным именем - Page#form, поэтому ваша строка для поиска формы станет

form = page.form('form1')

этот метод работает со старыми и новыми версиями.

1 голос
/ 20 марта 2009

Mechanize будет использовать hpricot внутри (это парсер по умолчанию для механизации). Более того, он передаст hpricot на анализатор, так что вам не придется делать это самостоятельно:

require 'rubygems'
require 'mechanize'

#You don't really need this if you don't use hpricot directly
require 'hpricot'

agent = WWW::Mechanize.new

page = agent.get('http://www.indiapost.gov.in/pin/pinsearch.aspx')

form = page.forms.find {|f| f.name == 'form1'}
form.fields.find {|f| f.name == 'ddl_state'}.options[1].select
page = agent.submit(form, form.buttons[2])

puts page.parser.to_html # page.parser returns the hpricot parser

puts page.at("//table[@id='gvw_offices']") # This passes through to hpricot

Также обратите внимание, что page.search("foo").first эквивалентно page.at("foo").

...