使用Nokogiri获取标题标记后的内容

时间:2016-01-05 16:06:20

标签: ruby nokogiri

我正在和Nokogiri一起玩,只是为了学习它,我正在尝试写一个小的CL刮刀。现在我试图将主页面上的每个州与下面的城市进行匹配。以下是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>

我已经可以推出这个&#34; colmask&#34;很容易。但是现在我只想在每个h4之后直接获得UL,但到目前为止还无法找到方法。建议?

2 个答案:

答案 0 :(得分:1)

使用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

答案 1 :(得分:1)

我做这样的事情:

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文件,该文件告诉您他们认为可以安全擦除的内容;忽视这可能导致被禁止。