使用Nokogiri解析HTML,并使用最接近的“"&书信电报;部门>&引用;
我的HTML包含:使用Nokogiri解析HTML,并使用最接近的“"&书信电报;部门>&引用;,html,ruby,nokogiri,Html,Ruby,Nokogiri,我的HTML包含: <div class = "s"> <p> text1 </p> <div class = "i"> <p> text2 </p> </div> </div> 这一切都很好,只是在我的数组中出现了“text2”,我不想要这些。因此,对于“text2”,最近的具有类“i”,我不希望在数组中看到它 我如何解决这个问题?可以有不同的类名和更深的嵌套,例如
<div class = "s">
<p> text1 </p>
<div class = "i">
<p> text2 </p>
</div>
</div>
这一切都很好,只是在我的数组中出现了“text2”
,我不想要这些。因此,对于“text2”
,最近的
具有类“i”
,我不希望在数组中看到它
我如何解决这个问题?可以有不同的类名和更深的嵌套,例如:
<div class = "s">
<p> text1 </p>
<div class = "i">
<p> text2 </p>
<div class = "s">
<p> text3 </p>
<div class = "p">
<p> text4 </p>
</div>
</div>
</div>
</div>
文本1
文本2
文本3
文本4
由此,我想得到一个数组:[“text1”,“text3”]
您可以执行以下操作:
html.css('.s > p').map {|node| node.text.strip }
这是一个更好的仅使用XPath的答案。我的原始答案如下
# Given a Nokogiri::HTML document in the `html` variable:
html.xpath("//text()[normalize-space() and ancestor::div[1][@class='s']]").map(&:text).map(&:strip)
这只会查找最近的div
祖先具有s
类的所有非空文本节点。这与我最初的答案是一样的,只是它完全是用XPath完成的
<div class = "s">
<p> text1 </p>
<div class = "i">
<p> text2 </p>
</div>
</div>
# => ["text1"]
<div class = "s">
<p> text1 </p>
<div class = "i">
<p> text2 </p>
<div class = "s">
<p> text3 </p>
<div class = "p">
<p> text4 </p>
</div>
</div>
</div>
</div>
# => ["text1", "text3"]
<div class = "s">
<div class='p'>
text 1
</div>
text 2
</div>
# => ["text 2"]
这里的基本思想是,我们找到从div.s
派生的所有文本节点,然后为每个文本节点找到最近的div
祖先,并且只接受具有类s
的最近的div祖先的节点
它有点CPU密集型,但满足了严格的要求。我从以下内容开始:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT, &:noblanks)
<div class = "s">
<p> text1 </p>
<div class = "i">
<p> text2 </p>
<div class = "s">
<p> text3 </p>
<div class = "p">
<p> text4 </p>
</div>
</div>
</div>
</div>
EOT
doc.search('.s').map{ |div| div.child.text.strip }
# => ["text1", "text3"]
这是一个古老的逻辑:
doc.search('.s').map{ |div| div.child.text.strip }
# => ["text1", "text3", "foobar"]
以及快速测试,以清除不需要的:
doc.search('.s').reject{ |div| div.child['class'] == 'i' }.map{ |div| div.child.text.strip }
# => ["text1", "text3"]
如果事物是嵌套的,那么结果也将嵌套。如何编写一个更好的选择器,以右
中的
为目标,例如:.s+p
@tadman有没有的can文本=(一个你正在处理的边缘案例的例子会有所帮助。你提供你试图解析的HTML的准确示例非常重要。不要让我们与你玩20个问题来了解真正的问题是什么,提供一个涵盖问题的最小示例。这有助于我们帮助你。所以你想要第一个非空白文本n包含在div
?中的ode,如果文本没有或其他标记?=(foobar
)将导致此技术失败。
require 'nokogiri'
doc = Nokogiri::XML(<<EOT, &:noblanks)
<div class = "s">
<p> text1 </p>
<div class = "i">
<p> text2 </p>
<div class = "s">
<p> text3 </p>
<div class = "p">
<p> text4 </p>
</div>
</div>
<div class='s'><div class='i'>foobar</div></div>
</div>
</div>
EOT
doc.search('.s').map{ |div| div.child.text.strip }
# => ["text1", "text3", "foobar"]
doc.search('.s').reject{ |div| div.child['class'] == 'i' }.map{ |div| div.child.text.strip }
# => ["text1", "text3"]