2017-02-27 56 views
0

帶有自定義屬性我有HTML與身體看起來像:如何得到div元素使用引入nokogiri

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

我想在上面身上所有的div元素,這將有dd:meta2屬性,所以,我只會得到一個div。

我寫了代碼來獲取div元素,但我收到一個錯誤,看起來像它與我在屬性中的:有關。

我的邏輯:

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

錯誤:

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

如何處理 ':' 在屬性?

回答

0

看起來Nokogiri不知道如何處理命名空間參數。下面是得到同樣結果的另一種方法:這將返回所有div節點與dd:meta2參數

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

同樣,你可以使用相同的用.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跑進your question on Nokogiri-Talk具有到引入nokogiri神解釋發生了什麼答案,並具有我建議同樣的解決方案之後。所以你有它。

0

我剛剛在昨天做了這個。這裏是我的html:

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

這裏是我的引入nokogiri表達:

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

這花了我從div標籤裏想出來的價值和剝下的超額收益。使用.try調用的原因是跳過必須讓if語句在返回nil時處理。這裏的祕密在於在.css表達式中使用[]:div [data-purpose = video-length]。