title = item.css("a")[0]['title']
是一種不好的做法。
而應考慮使用at
或at_css
代替search
或css
寫着:
title = item.at('a')['title']
接下來,如果返回的<a>
標籤沒有一個title
參數,引入nokogiri和/或Ruby將是苦惱的原因, title
變量將爲零。相反,提高你的CSS選擇器,只允許比賽就像<a title="foo">
:
require 'nokogiri'
doc = Nokogiri::HTML('<body><a href="foo">foo</a><a href="bar" title="bar">bar</a></body>')
doc.at('a').to_html # => "<a href=\"foo\">foo</a>"
doc.at('a[title]').to_html # => "<a href=\"bar\" title=\"bar\">bar</a>"
注意如何第一個,這是不限制以查找標記有title
參數返回第一<a>
標籤。使用a[title]
將只返回參數爲title
的參數。
這意味着你的循環遍歷值永遠不會返回零,並且你不會有返回的數組需要compact
的問題。
作爲一般的編程提示,如果你得到尼爾斯這樣,看代碼生成陣列,因爲賠率是好它沒有這樣做的權利。你應該總是知道什麼樣的結果,你的代碼生成。使用compact
清理陣列是不具有正確寫入的代碼的大部分時間下意識反應。
這是你更新的代碼:
require 'nokogiri'
require 'open-uri'
url = 'http://themagicway.taobao.com/search.htm?&search=y&orderType=newOn_desc'
doc = Nokogiri::HTML(open(url))
puts doc.css(".main-wrap .item").count
doc.css(".main-wrap .item").first(30).each do |item_info|
if item_info
href = item_info.at(".detail a")['href']
puts href
else
puts 'this is empty'
end
end
而這裏的什麼是錯的:
doc.css(".main-wrap .item").first(30)
這裏有一個簡單的例子表明,爲什麼不工作:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<html>
<body>
<p>foo</p>
</body>
</html>
EOT
在Nokogiri,search',
個CSS and
xpath`是等價的,但第一個是通用的,可以採取任何CSS或XPath,而最後兩個特定於該語言。
doc.search('p') # => [#<Nokogiri::XML::Element:0x3fcf360ef750 name="p" children=[#<Nokogiri::XML::Text:0x3fcf360ef4f8 "foo">]>]
doc.search('p').size # => 1
doc.search('p').map(&:to_html) # => ["<p>foo</p>"]
表明這些節點集返回做一個簡單的search
只返回一個節點,什麼節點樣子。
doc.search('p').first(2) # => [#<Nokogiri::XML::Element:0x3fe3a28d2848 name="p" children=[#<Nokogiri::XML::Text:0x3fe3a28c7b50 "foo">]>, nil]
doc.search('p').first(2).size # => 2
使用first(n)
進行搜索將返回「n」個元素。如果沒有發現那麼多,Nokogiri會使用零值來填充它們。
這是我們假定first(n)
要做的事情,因爲Enumerable#first
返回最多爲n,並且不會填充nils。這是不是一個錯誤,但它是意外的行爲,因爲可枚舉的first
集使用該名稱的方法預期的行爲,但是,這是NodeSet#first
,不Enumerable#first
,所以它做什麼,它直到引入nokogiri作者改變它。 (你可以看到爲什麼,如果你看一下源爲特定的方法它發生。)
相反,切片NODESET 不顯示預期的行爲:
doc.search('p')[0..1] # => [#<Nokogiri::XML::Element:0x3fe3a28d2848 name="p" children=[#<Nokogiri::XML::Text:0x3fe3a28c7b50 "foo">]>]
doc.search('p')[0..1].size # => 1
doc.search('p')[0, 2] # => [#<Nokogiri::XML::Element:0x3fe3a28d2848 name="p" children=[#<Nokogiri::XML::Text:0x3fe3a28c7b50 "foo">]>]
doc.search('p')[0, 2].size # => 1
所以,不要使用NodeSet#first(n)
,使用片形式NodeSet#[]
。
應用的是,我會寫的代碼是這樣的:
require 'nokogiri'
require 'open-uri'
URL = 'http://themagicway.taobao.com/search.htm?&search=y&orderType=newOn_desc'
doc = Nokogiri::HTML(open(URL))
hrefs = doc.css(".main-wrap .item .detail a[href]")[0..29].map { |anchors|
anchors['href']
}
puts hrefs.size
puts hrefs
# >> 24
# >> http://item.taobao.com/item.htm?id=41249522884
# >> http://item.taobao.com/item.htm?id=40369253621
# >> http://item.taobao.com/item.htm?id=40384876796
# >> http://item.taobao.com/item.htm?id=40352486259
# >> http://item.taobao.com/item.htm?id=40384968205
# >> http://item.taobao.com/item.htm?id=40384816312
# >> http://item.taobao.com/item.htm?id=40384600507
# >> http://item.taobao.com/item.htm?id=39973451949
# >> http://item.taobao.com/item.htm?id=39861209551
# >> http://item.taobao.com/item.htm?id=39545678869
# >> http://item.taobao.com/item.htm?id=39535371171
# >> http://item.taobao.com/item.htm?id=39509186150
# >> http://item.taobao.com/item.htm?id=38973412667
# >> http://item.taobao.com/item.htm?id=38910499863
# >> http://item.taobao.com/item.htm?id=38942960787
# >> http://item.taobao.com/item.htm?id=38910403350
# >> http://item.taobao.com/item.htm?id=38843789106
# >> http://item.taobao.com/item.htm?id=38843517455
# >> http://item.taobao.com/item.htm?id=38854788276
# >> http://item.taobao.com/item.htm?id=38825442050
# >> http://item.taobao.com/item.htm?id=38630599372
# >> http://item.taobao.com/item.htm?id=38346270714
# >> http://item.taobao.com/item.htm?id=38357729988
# >> http://item.taobao.com/item.htm?id=38345374874
非常感謝。我希望我能同時接受2個答案。很有幫助! – cqcn1991 2014-10-03 13:39:03
真正的問題是這樣的。我想獲得一頁20個項目。所以我用'first(20)'編寫一個選擇器。但是,它可能只有15個項目。所以剩餘的20個陣列將有15個項目+ 5個零。我不覺得這可以通過使用更好的選擇器來改進,而是將「第一(20)」更改爲更合適的方式。但我不知道如何。 – cqcn1991 2014-10-03 13:50:18
'[] .first(2)#=> []'。除非你不正確地處理數組,否則你不能得到「15 + 5無」,你只能得到15。這是基於很多經驗處理網站。所以,問題不在於你如何請求20,而是你在做什麼。 – 2014-10-03 16:41:03