我和Nokogiri一起玩只是为了学习它,并试图写一个小CL scraper。现在,我正试图将主页上的每个州与下面的城市进行匹配。以下是HTML的一个片段:
<div class="colmask">
<div class="box box_1">
<h4>Alabama</h4>
<ul>
<li><a href="//auburn.craigslist.org/">auburn</a></li>
<li><a href="//bham.craigslist.org/">birmingham</a></li>
<li><a href="//dothan.craigslist.org/">dothan</a></li>
<li><a href="//shoals.craigslist.org/">florence / muscle shoals</a></li>
<li><a href="//gadsden.craigslist.org/">gadsden-anniston</a></li>
<li><a href="//huntsville.craigslist.org/">huntsville / decatur</a></li>
<li><a href="//mobile.craigslist.org/">mobile</a></li>
<li><a href="//montgomery.craigslist.org/">montgomery</a></li>
<li><a href="//tuscaloosa.craigslist.org/">tuscaloosa</a></li>
</ul>
<h4>Alaska</h4>
<ul>
<li><a href="//anchorage.craigslist.org/">anchorage / mat-su</a></li>
<li><a href="//fairbanks.craigslist.org/">fairbanks</a></li>
<li><a href="//kenai.craigslist.org/">kenai peninsula</a></li>
<li><a href="//juneau.craigslist.org/">southeast alaska</a></li>
</ul>
我已经可以很容易地提取出"colmask"的这个div类了。但现在我只是想在每个h4之后直接获得UL,但到目前为止还找不到方法。建议?
您可以使用following-sibling
:在h4之后获得ul元素
require 'nokogiri'
html = <<-EOF
<div class="colmask">
<div class="box box_1">
<h4>Alabama</h4>
<ul>
<li><a href="//auburn.craigslist.org/">auburn</a></li>
<li><a href="//bham.craigslist.org/">birmingham</a></li>
<li><a href="//dothan.craigslist.org/">dothan</a></li>
<li><a href="//shoals.craigslist.org/">florence / muscle shoals</a></li>
<li><a href="//gadsden.craigslist.org/">gadsden-anniston</a></li>
<li><a href="//huntsville.craigslist.org/">huntsville / decatur</a></li>
<li><a href="//mobile.craigslist.org/">mobile</a></li>
<li><a href="//montgomery.craigslist.org/">montgomery</a></li>
<li><a href="//tuscaloosa.craigslist.org/">tuscaloosa</a></li>
</ul>
<h4>Alaska</h4>
<ul>
<li><a href="//anchorage.craigslist.org/">anchorage / mat-su</a></li>
<li><a href="//fairbanks.craigslist.org/">fairbanks</a></li>
<li><a href="//kenai.craigslist.org/">kenai peninsula</a></li>
<li><a href="//juneau.craigslist.org/">southeast alaska</a></li>
</ul>
EOF
doc = Nokogiri::HTML(html)
doc.xpath('//h4/following-sibling::ul').each do |node|
puts node.to_html
end
要在h4后面选择ul,请使用精确文本:
puts doc.xpath("//h4[text()='Alabama']/following-sibling::ul")[0].to_html
我会这样做:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<h4>Alabama</h4>
<ul>
<li><a href="//auburn.craigslist.org/">auburn</a></li>
<li><a href="//bham.craigslist.org/">birmingham</a></li>
</ul>
<h4>Alaska</h4>
<ul>
<li><a href="//anchorage.craigslist.org/">anchorage / mat-su</a></li>
<li><a href="//fairbanks.craigslist.org/">fairbanks</a></li>
</ul>
EOT
states = doc.search('h4')
states_and_cities = states.map{ |state|
cities = state.next_element.search('li a')
[state.text, cities.map(&:text)]
}.to_h
此时states_and_cities
是数组的散列:
states_and_cities
# => {"Alabama"=>["auburn", "birmingham"],
# "Alaska"=>["anchorage / mat-su", "fairbanks"]}
如果你担心有一个大的结构,那么很容易将states
转换为哈希,其中每个州的名称都是一个键,相关的值是该州的节点。然后,可以抓住该节点,只查找特定州的城市。
然而,如果您正在运行此代码来动态生成网页内容,那么您就错了。各州和城市的信息应该被转储到一个数据库中,在那里可以更快地访问。这样就不必每次生成页面时都这样做了。
对其他网站友善和温柔是很重要的;研究HEAD
HTTP请求。这是决定是否应该完整检索页面的关键。此外,学习如何从服务器返回的HTTP标头中探查缓存信息。这告诉你的最低刷新率应该是多少。此外,请注意robots.txt文件,它告诉你他们认为你可以安全地抓取什么;忽视这一点可能导致被禁止。