我有一个这样的HTML结构:
<div>
This is
<p> very
<script>
some code
</script>
</p>
important.
</div>
我知道如何从中得到Nokogiri::XML::NodeSet
:
dom.xpath("//div")
我现在想过滤掉任何script
标签:
dom.xpath("//script")
所以我可以得到这样的东西:
<div>
This is
<p> very</p>
important.
</div>
这样我就可以打电话给div.text
来获取:
"This is very important."
我尝试递归/迭代地遍历所有子节点,并尝试匹配每个节点,我想过滤掉我不想要的任何节点,但我遇到了空格过多或空格不足等问题。我很确定有一种足够好和红宝石的方式。
这样做的好方法是什么?
NodeSet 包含 remove
方法,可以轻松删除与您的选择器匹配的任何内容:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<html>
<body>
<div><p>foo</p><p>bar</p></div>
</body>
</html>
EOT
doc.search('p').remove
puts doc.to_html
# >> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
# >> <html>
# >> <body>
# >> <div></div>
# >> </body>
# >> </html>
应用于示例输入:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<div>
This is
<p> very
<script>
some code
</script>
</p>
important.
</div>
EOT
doc.search('script').remove
puts doc.to_html
# >> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
# >> <html><body>
# >> <div>
# >> This is
# >> <p> very
# >>
# >> </p>
# >> important.
# >> </div>
# >> </body></html>
此时,<div>
中的文本是:
doc.at('div').text # => "n This isn veryn n n important.n"
规范化这很容易:
doc.at('div').text.gsub(/[n ]+/,' ').strip # => "This is very important."
第一个问题
要删除所有脚本节点:
require 'nokogiri'
html = "<div>
This is
<p> very
<script>
some code
</script>
</p>
important.
</div>"
doc = Nokogiri::HTML(html)
doc.xpath("//script").remove
p doc.text
#=> "n This isn veryn n n important.n"
感谢@theTinMan的提示(在一个节点集而不是每个节点上调用remove
)。
第二个问题
要删除不需要的空格,您可以使用:
-
strip
删除字符串开头和结尾的空格(空格、制表符、换行符等) -
gsub
仅用一个空格替换多个空格
p doc.text.strip.gsub(/[[:space:]]+/,' ')
#=> "This is very important."