【问题标题】:hpricot with firebug's XPathhpricot 与 firebug 的 XPath
【发布时间】:2010-08-22 08:43:44
【问题描述】:

我正在尝试使用 hpricot 从基于表格的网站中提取一些信息。我得到了带有 FireBug 的 XPath。

/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

这不起作用... 显然,FireBug 的 XPath 是呈现的 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 中没有。

我做错了什么,或者有没有更好的工具来使用长/复杂的 XPath 废弃 HTML。

【问题讨论】:

    标签: ruby xpath firebug hpricot


    【解决方案1】:

    您的问题出在 XPather(或 firebug XPath)中。 我认为 Firefox 正在内部修复格式错误的表格以具有 tbody 元素,即使在 HTML 中没有。 Nokogiri 没有这样做,而是允许 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
    

    祝你好运

    【讨论】:

      【解决方案2】:

      使用 hpricot 的 CSS 解析而不是 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,一些 cmets 暗示在进行类似于以下的嵌套搜索时,CSS 版本如何优于 XPath你是什​​么人。

      希望我能给出更好的答案,但我强烈建议先试一试 CSS 方法,看看它是如何运行的,然后再用 XPath 解决问题。

      【讨论】:

        【解决方案3】:

        我现在正在使用 css,我用这个很棒的工具“计算”它:www.selectorgadget.com

        【讨论】:

          【解决方案4】:

          可能值得注意的是,Nokogiri 使用与 Hpricot 相同的 API,但也支持 XPath 表达式。

          【讨论】:

            【解决方案5】:

            您的 HTML 代码中没有 TBODY 标记。 Firebug 会自动生成它。

            【讨论】:

              猜你喜欢
              • 2010-12-25
              • 2011-01-18
              • 2010-09-17
              • 1970-01-01
              • 1970-01-01
              • 2011-02-22
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多