【问题标题】:Searching all elements before an h2 element in hpricot/nokogiri在 hpricot/nokogiri 中搜索 h2 元素之前的所有元素
【发布时间】:2010-11-29 23:04:27
【问题描述】:

我正在尝试解析一个维基词典条目以检索所有英文定义。我能够检索所有定义,问题是某些定义是其他语言的。我想做的是以某种方式只检索带有英文定义的 HTML 块。我发现,在有其他语言条目的情况下,可以通过以下方式检索英文定义后的标题:

header = (doc/"h2")[3]

所以我只想搜索此标题元素之前的所有元素。我认为header.preceding_siblings() 可能有可能,但这似乎不起作用。有什么建议吗?

【问题讨论】:

    标签: ruby parsing nokogiri hpricot wiktionary


    【解决方案1】:

    您可以通过 Nokogiri 使用访问者模式。此代码将删除从其他语言定义的 h2 开始的所有内容:

    require 'nokogiri'
    require 'open-uri'
    
    class Visitor
      def initialize(node)
        @node = node
      end
    
      def visit(node)
        if @remove || @node == node
          node.remove
          @remove = true
          return
        end
        node.children.each do |child|
          child.accept(self)
        end
      end
    end
    
    doc = Nokogiri::XML.parse(open('http://en.wiktionary.org/wiki/pony'))
    node = doc.search("h2")[2]  #In this case, the Italian h2 is at index 2.  Your page may differ
    
    doc.root.accept(Visitor.new(node))  #Removes all page contents starting from node
    

    【讨论】:

      【解决方案2】:

      以下代码使用 Hpricot
      它从英语语言 (h2) 的标题中获取文本,直到下一个标题 (h2),或者如果没有其他语言,则直到页脚:

      require 'hpricot'
      require 'open-uri'
      
      def get_english_definition(url)
        doc = Hpricot(open(url))
      
        span = doc.at('h2/span[@class="mw-headline"][text()=English]')
        english_header = span && span.parent
        return nil unless english_header
      
        next_header_or_footer =
          Hpricot::Elements[*english_header.following_siblings].at('h2') ||
          doc.at('[@class="printfooter"]')
      
        Hpricot::Elements.expand(english_header.next_node,
                                 next_header_or_footer.previous_node).to_s
      end
      

      示例:

      get_english_definition "http://en.wiktionary.org/wiki/gift"
      

      【讨论】:

        【解决方案3】:

        对于Nokogiri:

        doc = Nokogiri::HTML(code)
        stop_node = doc.css('h2')[3]
        doc.traverse do |node|
          break if node == stop_node
          # else, do whatever, e.g. `puts node.name`
        end
        

        这将遍历您在第 2 行中指定为 stop_node 的任何节点之前的所有节点。

        【讨论】:

          猜你喜欢
          • 2015-06-02
          • 1970-01-01
          • 2020-05-10
          • 1970-01-01
          • 1970-01-01
          • 2012-03-07
          • 1970-01-01
          • 2011-03-09
          • 2021-07-02
          相关资源
          最近更新 更多