如何使用 Nokogiri 获取具有自定义属性的 div 元素



我有 HTML,正文看起来像:

<body>
<div class="myclass" dd:meta1="meta data 1" dd:meta2="CD5503253E54"></div>
<div class="myclass" dd:meta1="meta data 11"></div>
</body>

我想获取所有具有dd:meta2属性的div 元素,因此在上面的正文中,我将只获得一个div。

我编写了代码来获取div 元素,但我收到一个错误,看起来它与我在属性中的:有关。

我的逻辑:

page = Nokogiri::HTML(html_string)
meta_data_divs = page.css('body').css("div[dd:meta2]")

错误:

unexpected ':' after '#<Nokogiri::CSS::Node:0x007fac6b986d58>'

如何处理属性中的":"?

实际上我昨天才这样做。 这是我的 html:

<div data-purpose="video-length">[^>]+</div>

这是我的nokogiri表情:

page.parser.css("div[data-purpose=video-length]").first.try(:text).try(:strip)

这从div 标签中取出了我想要的值,并剥离了额外的回报。 使用 .try 调用的原因是跳过在返回 nil 时必须处理的 if 语句。 这里的秘密在于在.css表达式中使用 []:div[data-purpose=video-length]。

看起来Nokogiri不知道如何处理命名空间参数。以下是获得相同结果的另一种方法:

require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<body>
<div class="myclass" dd:meta1="meta data 1" dd:meta2="CD5503253E54"></div>
<div class="myclass" dd:meta1="meta data 11"></div>
</body>
EOT
doc.search('div').select{ |div| div.attributes.include?('dd:meta2') }
# => [#(Element:0x3fea99895530 {
#       name = "div",
#       attributes = [
#         #(Attr:0x3fea99895508 { name = "class", value = "myclass" }),
#         #(Attr:0x3fea998954f4 { name = "dd:meta1", value = "meta data 1" }),
#         #(Attr:0x3fea998954e0 { name = "dd:meta2", value = "CD5503253E54" })]
#       })]

这将返回所有带有dd:meta2参数的div节点。

类似地,您可以使用相同的方法.first末端固定来充当at,但它不会像以下那样快:

doc.search('div').find{ |div| div.attributes.include?('dd:meta2') }
# => #(Element:0x3fea99895530 {
#      name = "div",
#      attributes = [
#        #(Attr:0x3fea99895508 { name = "class", value = "myclass" }),
#        #(Attr:0x3fea998954f4 { name = "dd:meta1", value = "meta data 1" }),
#        #(Attr:0x3fea998954e0 { name = "dd:meta2", value = "CD5503253E54" })]
#      })

这将比您尝试的方式慢一些,因为它会导致解析器搜索整个文档并返回所有div标签,然后 Ruby 将不得不筛选结果以找到具有所需参数的节点。但它将比引发异常的代码快得多。

我建议向Nokogiri团队提交错误报告,向他们展示问题。


呵,写完之后,我搜索了dd:meta2并在Nokogiri-Talk上遇到了您的问题,其中有Nokogiri神的答案,解释了正在发生的事情,并且与我建议的解决方案相同。所以你有它。

最新更新