2

我有一些 HTML 页面,其中要提取的内容标有 HTML 注释,如下所示。

<html>
 .....
<!-- begin content -->
 <div>some text</div>
 <div><p>Some more elements</p></div>
<!-- end content -->
...
</html>

我正在使用 Nokogiri 并尝试提取 <!-- begin content --><!-- end content -->注释之间的 HTML。

我想提取这两个 HTML 注释之间的完整元素:

<div>some text</div>
<div><p>Some more elements</p></div>

我可以使用此字符回调获取纯文本版本:

class TextExtractor < Nokogiri::XML::SAX::Document

  def initialize
    @interesting = false
    @text = ""
    @html = ""
  end

  def comment(string)
    case string.strip        # strip leading and trailing whitespaces
    when /^begin content/      # match starting comment
      @interesting = true
    when /^end content/
    @interesting = false   # match closing comment
  end

  def characters(string)
    @text << string if @interesting
  end

end

我得到了纯文本版本,@text但我需要将完整的 HTML 存储在@html.

4

1 回答 1

6

在两个节点之间提取内容不是我们通常会做的事情;通常我们希望内容在特定节点内。评论是节点,它们只是特殊类型的节点。

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<body>
<!-- begin content -->
 <div>some text</div>
 <div><p>Some more elements</p></div>
<!-- end content -->
</body>
EOT

通过查找包含指定文本的注释,可以找到起始节点:

start_comment = doc.at("//comment()[contains(.,'begin content')]") # => #<Nokogiri::XML::Comment:0x3fe94994268c " begin content ">

一旦找到,就需要一个循环来存储当前节点,然后寻找下一个兄弟节点,直到找到另一个注释:

content = Nokogiri::XML::NodeSet.new(doc)
contained_node = start_comment.next_sibling
loop do
  break if contained_node.comment?
  content << contained_node
  contained_node = contained_node.next_sibling
end

content.to_html # => "\n <div>some text</div>\n <div><p>Some more elements</p></div>\n"
于 2013-09-18T16:15:26.510 回答