在hpricot / nokogiri中搜索h2元素之前的所有元素

时间:2009-09-21 00:46:48

标签: ruby parsing nokogiri hpricot wiktionary

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

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

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

3 个答案:

答案 0 :(得分:2)

您可以使用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

答案 1 :(得分:1)

以下代码使用 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"

答案 2 :(得分:1)

对于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的任何节点之前的所有节点。