【问题标题】:Nokogiri extract nodes from htmlNokogiri 从 html 中提取节点
【发布时间】:2013-01-11 00:19:07
【问题描述】:

我需要从 html 中提取节点(不是内部文本,因此我可以保留格式以供进一步手动调查)。我写了下面的代码。但由于 traverse 的工作原理,我在新的 html 文件中得到了重复项。

这是真正要解析的 html。 http://www.sec.gov/Archives/edgar/data/1750/000104746912007300/a2210166z10-k.htm

基本上我需要将Item10和“注册人的执行官”之间的部分提取到下一个Item。第 10 项在所有文件中,但“注册人的执行官”并非在所有文件中。我需要获取节点而不仅仅是文本,因为我想保留表格,所以在下一步中,我可以解析这些部分中的表格(如果有的话)。

示例 html:

html = "
<BODY>
<P>Dont need this </P>  
<P>Start</P>
<P>Text To Extract 1 </P>
<P><Font><B>Text to Extract 2 </B></Font></P>
<DIV><TABLE>
<TR>
<TD>Text to Extract 3</TD>
<TD>Text to Extract 4</TD>
</TR>
</TABLE></DIV>
<P>End</P>
</BODY>
"

我想得到:

html = "
<BODY>
<P>Start</P>
<P>Text To Extract 1 </P>
<P><Font><B>Text to Extract 2 </B></Font></P>
<DIV><TABLE>
<TR>
<TD>Text to Extract 3</TD>
<TD>Text to Extract 4</TD>
</TR>
</TABLE></DIV>
<P>End</P>
</BODY>
"

当 start_keyword 出现时开始提取。 当 end_keyword 出现时结束提取。

我需要从一个 html 中提取多个部分。关键字可以出现在不同名称的节点中。

doc.at_css('body').traverse do |node|
    inMySection  = false

    if node.text.match(/#{start_keyword}/)
        inMySection = true
    elsif node.text.match(/#{end_keyword}/)
        inMySection = false
    end
    if inMySection
        #Extract the nodes
    end
end

参考这些帖子后,我也尝试使用xpath来实现这一点,但没有成功:

XPath axis, get all following nodes until

XPath to find all following siblings up until the next sibling of a particular type

【问题讨论】:

  • 如果您可以发布您从中提取的 html 的示例,将会有所帮助。
  • 关键字是明文,可以存在于文档任意位置的文本节点中吗?是否要提取包含 start 关键字的节点?父容器?我同意@shioyama 的观点,你应该发布一个样本,我认为你还应该展示你想要提取的内容。
  • 没有 HTML 来测试我们是在黑暗中拍摄,编写测试用例。而且,是否有错误,或者我们应该弥补一个错误?如果有错误,请告诉我们哪里出了问题。
  • 关键字可以在段落中间吗?当它们跨越层次结构时会发生什么,例如&lt;div&gt;&lt;p&gt;START content&lt;/p&gt;&lt;/div&gt;&lt;p&gt;And then &lt;b&gt;we END&lt;/b&gt;&lt;/p&gt;?应该提取什么内容?
  • 抱歉回复晚了。以为我设置了电子邮件警报,但没有收到任何电子邮件。添加了示例 html。

标签: html ruby nokogiri


【解决方案1】:

这不是 Nokogiri 的问题,而是你的算法的问题。您已将标志 inMySection 放入循环中,这意味着在每个步骤中您再次将其设置为 false,如果之前设置为 true,您将失败。

根据您的示例 HTML 输入和输出,以下 sn-p 有效:

nodes = Nokogiri::HTML(html)
inMySection  = false
nodes.at_xpath('//body').traverse do |node|
  if node.text.match(/Start/)
    inMySection = true
  elsif node.text.match(/End/)
    inMySection = false
  end
  node.remove unless inMySection
end
print nodes

【讨论】:

    猜你喜欢
    • 2016-01-18
    • 1970-01-01
    • 2012-06-27
    • 1970-01-01
    • 1970-01-01
    • 2012-06-12
    • 2015-02-02
    • 1970-01-01
    • 2018-05-03
    相关资源
    最近更新 更多