title = item.css("a")[0]['title']
나쁜 방법입니다. 대신
, at
또는 at_css
대신 search
또는 css
를 사용하여 작성 고려해 반환 <a>
태그가 title
매개 변수가없는 경우
가
title = item.at('a')['title']
다음, 노코 기리 및/또는 루비 화가 될 것입니다 때문에 title
변수는 0이됩니다. 대신에, 단지 <a title="foo">
처럼 일치를 허용하도록 CSS 선택기를 개선 : 제한되지 않는, 첫 번째는 title
매개 변수를 사용하여 태그를 찾는 방법
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>"
공지 사항 첫 번째 <a>
태그를 반환합니다. a[title]
을 사용하면 title
매개 변수가있는 매개 변수 만 반환됩니다.
즉, 값을 둘러싼 루프는 결코 nil을 반환하지 않으므로 반환 된 배열에서 compact
개의 문제가 발생하지 않아도됩니다.
일반적으로 프로그래밍 팁 에서처럼 nils가 좋으면 확률이 좋기 때문에 배열을 생성하는 코드를 살펴보십시오. 항상 코드가 어떤 결과를 생성하는지 알고 있어야합니다. 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
그리고 여기 뭐가 잘못이다 :
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<html>
<body>
<p>foo</p>
</body>
</html>
EOT
:
이
doc.css(".main-wrap .item").first(30)
여기서 문제가 해결되지 않는 이유를 설명하는 간단한 예제 Nokogiri에서 search',
css and
xpath`는 첫 번째가 제네릭이고 CSS 또는 XPath 중 하나를 사용할 수 있다는 것을 제외하고는 마지막 두 개는 해당 언어에만 해당합니다. 노드 집합 간단한 search
반환에게 하나 개의 노드 만, 어떤 노드의 모양을 수행하여 반환 된 것을 알 수
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>"]
.
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가 nil 값을 사용하여 채 웁니다.
Enumerable#first
이 n을 반환하고 nils로 채우지 않으므로이 값이 first(n)
이라고 가정 할 때 카운터입니다. 이것은 버그가 아니지만 Enumerable의 first
이 해당 이름의 메소드에 대해 예상되는 동작을 설정했기 때문에 예기치 않은 동작이지만 NodeSet#first
이 아니라 Enumerable#first
이 아니므로 Nokogiri 작성자가 변경하기 전까지 수행하는 작업을 수행합니다. (당신이 특정 방법에 대한 소스를 보면 그런 일이 이유를 확인할 수 있습니다.)
을 대신 가이 예상되는 동작 보여 않는 노드 세트를 얇게 : 그래서
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
진짜 문제는 바로 그것입니다. 나는 20 페이지의 항목을 얻고 싶다.그래서 나는'first (20) '를 써서 선택자를 쓴다. 그러나 15 개의 항목 만있을 수 있습니다. 나머지 20 개 배열은 15 개 + 5 개입니다. 더 나은 셀렉터를 사용하여 개선 될 수 있다고 생각하지 않지만'first (20)'을보다 적절한 방법으로 변경하십시오. 하지만 어떻게해야할지 모르겠다. – cqcn1991
'[] .first (2) # => []'. 배열을 잘못 처리하지 않는 한 "15 + 5 nil"을 얻을 수 없습니다. 단지 15를 얻게됩니다. 더 나은 선택자가 * 도움을 줄 것입니다. 이것은 많은 경험 처리 사이트를 기반으로합니다. 그래서, 문제는 당신이 20을 요청하는 방법이 아니라, 당신이 나중에하고있는 것입니다. –