使用 Nokogiri 获取 header 标签后的内容
Get content after header tag with 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>
我已经可以轻而易举地取出 "colmask" 的 div class 了。但是现在我只是想在每个 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
到 select ul 在 h4 之后用准确的文本:
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
转换为散列非常容易,其中每个状态的名称是一个键,关联的值是状态的节点。然后,可以抓取该节点以仅查找特定州的城市。
但是,如果您 运行 使用此代码即时生成 web-page 的内容,那么您就错了。州和城市的信息应该存入一个数据库,在那里可以更快地访问它。这样就不用每次生成页面都做。
对其他网站友善和温柔很重要;研究 HEAD
HTTP 请求。这是决定是否应完整检索页面的关键。此外,了解如何从服务器返回的 HTTP header 中嗅探缓存信息。这告诉您最低刷新率应该是多少。另外,请注意 robots.txt 文件,它会告诉您他们认为您可以安全抓取的内容;忽略可能导致被禁止。
我正在玩 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>
我已经可以轻而易举地取出 "colmask" 的 div class 了。但是现在我只是想在每个 h4 之后直接获取 UL,但到目前为止还找不到办法。建议?
您可以使用 following-sibling
:
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
到 select ul 在 h4 之后用准确的文本:
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
转换为散列非常容易,其中每个状态的名称是一个键,关联的值是状态的节点。然后,可以抓取该节点以仅查找特定州的城市。
但是,如果您 运行 使用此代码即时生成 web-page 的内容,那么您就错了。州和城市的信息应该存入一个数据库,在那里可以更快地访问它。这样就不用每次生成页面都做。
对其他网站友善和温柔很重要;研究 HEAD
HTTP 请求。这是决定是否应完整检索页面的关键。此外,了解如何从服务器返回的 HTTP header 中嗅探缓存信息。这告诉您最低刷新率应该是多少。另外,请注意 robots.txt 文件,它会告诉您他们认为您可以安全抓取的内容;忽略可能导致被禁止。