hpricot с XPath клопа - PullRequest
       34

hpricot с XPath клопа

2 голосов
/ 09 апреля 2009

Я пытаюсь извлечь некоторую информацию из табличного веб-сайта с помощью hpricot. Я получаю XPath с FireBug.

/html/body/div/table/tbody/tr/td/table/tbody/tr[2]/td/table/tbody/tr/td[2]/table/tbody/tr[3]/td/table[3]/tbody/tr

Это не работает ... Судя по всему, XPath FireBug - это путь к отображаемому HTML, а не фактический HTML с сайта. Я прочитал, что удаление tbody может решить проблему.

Я пытаюсь с:

/html/body/div/table/tr/td/table/tr[2]/td/table/tr/td[2]/table/tr[3]/td/table[3]/tr

И все еще не работает ... Я провожу немного больше исследований, и некоторые люди сообщают, что XPath удаляет числа, поэтому я попробую это:

/html/body/div/table/tr/td/table/tr/td/table/tr/td/table/tr/td/table/tr

Все еще не повезло ...

Так что я решил сделать это шаг за шагом, как это:

(doc/"html/body/div/table/tr").each do |aaa |
  (aaa/"td").each do | bbb|
        pp bbb
        (bbb/"table/tr").each do | ccc|
            pp ccc 
      end
  end
end

Я нахожу нужную информацию в bbb, но не в ccc.

Что я делаю не так, или есть лучший инструмент для удаления HTML с длинным / сложным XPath.

Ответы [ 5 ]

4 голосов
/ 09 июня 2009

Ваша проблема в XPather (или XPath для firebug). Firefox, я думаю, внутренне исправляет плохо отформатированные таблицы, чтобы иметь элемент tbody, даже если в HTML его нет. Нокогири этого не делает, вместо этого он позволяет тегу tr находиться внутри таблицы.

так что велика вероятность того, что ваш путь выглядит к нокогири так:

/html/body/div/table/tr/td/table/tr[2]/td/table/tr/td[2]/table/tr[3]/td/table[3]/tr

и вот как nokogiri примет это:)

Вы можете проверить это

require 'open-uri'
require 'nokogiri'

class String
  def relative_to(base)
    (base == self[0..base.length-1]) &&
      self[base.length..-1]
  end
end

module Importer
  module XUtils
    module_function

    def match(text, source)
      case text
      when String
        source.include? text
      when Regexp
        text.match(source)
      when Array
        text.all? {|tt| source.include?(tt)}
      else
        false
      end
    end

    def find_xpath (doc, start, texts)
      xpath = start
      found = true

      while(found)
        found = [:inner_html, :inner_text].any? do |m|
          doc.xpath(xpath+"/*").any? do |tag|
            tag_text = tag.send(m).strip.gsub(/[\302\240]+/, ' ')
            if tag_text && texts.all?{|text| match(text, tag_text)}
              xpath = tag.path.to_s
            end
          end
        end
      end

      (xpath != start) && xpath
    end

    def fetch(url)
      Nokogiri::HTML(open(url).read)
    end
  end
end

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

основное использование:

 include XUtils
 doc = fetch("http://some.url.here") # http:// is impotrtant!

 base = find_xpath(doc, '/html/body', ["what to find1", "What to find 2"]) # when you provide array, then it'll find element conaining ALL words

 precise = find_xpath(doc, base, "what to find1")
 precise.relative_to base

Удачи

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

Я сейчас использую css и «вычисляю» его с помощью этого замечательного инструмента: www.selectorgadget.com

1 голос
/ 11 мая 2009

Вероятно, стоит отметить, что Nokogiri использует тот же API, что и Hpricot, но также поддерживает выражения XPath.

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

Возможно, вам лучше использовать CSS-анализ hpricot вместо XPath. Почему в какой-то момент речь шла о возможном ограничении XPath.

У вас есть лучший пример данных? Используют ли они теги CSS, на которые легко ссылаться?

Поиск гораздо проще, например:

doc.search("#id_tag > table > tr.class_tag > td").each do |aaa|
    aaa.search("blah > blah").each do |bbb|
        bbb.inner_html

На веб-сайте _why была старая страница (которую я сейчас не могу найти), в которой обсуждался hpricot, и в некоторых комментариях указывалось на то, что версия CSS была лучшим выбором по сравнению с XPath при выполнении вложенных поисков, подобных кто ты.

Хотелось бы дать лучший ответ, но я настоятельно рекомендую попробовать метод CSS и посмотреть, как он работает, прежде чем рвать на себе волосы с помощью XPath.

0 голосов
/ 22 августа 2010

В вашем HTML-коде нет тега TBODY. Firebug генерирует его автоматически.

...