如何使用Nokogiri

时间:2017-02-27 20:18:56

标签: html css ruby nokogiri

我的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>'

我如何处理&#39;:&#39;在属性?

2 个答案:

答案 0 :(得分:1)

我昨天才这样做了。这是我的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]。

答案 1 :(得分:0)

看起来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" })]
#       })]

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

同样地,您可以使用相同的.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

这会比你尝试它的速度慢一些,因为它会导致解析器搜索整个文档并返回所有dd:meta2标记,然后Ruby将不得不筛选结果以查找节点使用所需的参数。但它会比引发异常的代码快得多。

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

嘿,在写完之后,我搜索了antialiased = True并遇到了your question on Nokogiri-Talk,其中有来自Nokogiri神的回答,解释了正在发生的事情,这与我建议的解决方案相同。所以你有它。