使用Nokogiri在HTML文件中解析多个列表

时间:2014-09-24 00:03:07

标签: ruby hash html-parsing nokogiri

我正在尝试用Ruby学习脚本,这是我的第一个问题。

我有一个包含州及其城市的HTML文件。我需要能够在我的Ruby代码中访问城市并知道它们属于哪个州,所以我计划解析HTML并为每个城市创建一个哈希,如下所示:{New York =>纽约市}。

我正在尝试使用Nokogiri,我现在才开始学习。

  <h4>State</h4>
  <ul>
    <li>city</li>
    <li>city</li>
    <li>city</li>
  </ul>
  <h4>State</h4>
  <ul>
    <li>city</li>
    <li>city</li>
    <li>city</li>
  </ul>
  <h4>State</h4>
  <ul>
    <li>city</li>
    <li>city</li>
    <li>city</li>
  </ul>

我正在使用它将状态变为数组:

require 'rubygems'
require 'nokogiri'

page = Nokogiri::HTML(open("to_parse.html"))

states = Array.new(100), index = 0

page.css('h4').each do |s|

    states[index]   = s.text
    puts states[index]

    index += 1
end

这实际上并没有真正帮助;我需要弄清楚如何让Nokogiri将每个列表的元素解析为包含城市及其状态的hashes。我不确定如何在完成一个州的城市列表时有一个循环中断,并为下一个州的城市列表创建一组新的hashes

我想我必须为每个列表元素创建一个hash,并在每个h4内存储该列表的hash标记文本,所以我知道哪个这个城市属于。这就是我不确定该怎么做。

随意提供一些关于重构我所得到的建议,因为我知道它可以做得更好。

1 个答案:

答案 0 :(得分:1)

XPath选择器可以帮助你。

states = doc.css('li').map do |city|
  state = city.xpath('../preceding-sibling::h4[1]')
  [city.text, state.text]
end.to_h

#=> {'city' => 'State', ...}

这会抓取所有li城市元素,然后追溯到他们的状态。 (XPath如下所示:.. =向上一级,preceding-sibling::h4 =前面的h4元素,[1] =第一个这样的元素)

对您的代码的一些评论:在Ruby中,您不需要初始化数组,并且使用像map这样的Enumerable方法,您永远不需要在循环中跟踪索引变量。

请注意,最终的to_h仅适用于Ruby 2.1或更高版本。