从Nokogiri获取桌子信息?

时间:2014-02-05 06:09:00

标签: html ruby parsing nokogiri

我正在尝试获取此网站规范的信息:

http://www.gsmarena.com/nokia_lumia_1520-5760.php

理想情况下,我会有这样的哈希:

{'General' => ['2G Network' => 'GSM 850 / 900 / 1800 / 1900 - all versions', 
               '3G Network' => 'HSDPA 850 / 900 / 1900 / 2100 - RM-937, RM-939, RM-940',
               '4G Network' => 'LTE 800 / 900 / 1800 / 2100 / 2600 - RM-937',
               ...
 'Body' => ['Dimensions' =>...
}

到目前为止我已经这样做了:

results = {}
tables = html.css('#specs-list table')
tables.each do |table|
  category_key = table.css('th').text
  results[category_key] = []
  rows = table.css('tr')

  rows.each do |row|
    spec_key = row.css('.ttl').text
    spec_content = row.css('.nfo').text
    results[category_key] << {spec_key => spec_content}
  end
end

问题在于,例如对于3G网络,有两行,我不知道如何在我的哈希中使用3G网络索引。

这对我来说很复杂:

<tbody><tr>
<th rowspan="8" scope="row">General</th>
<td class="ttl"><a href="network-bands.php3">2G Network</a></td>
<td class="nfo">GSM 850 / 900 / 1800 / 1900 - all versions</td>
</tr><tr>
<td class="ttl"><a href="network-bands.php3">3G Network</a></td>
<td class="nfo">HSDPA 850 / 900 / 1900 / 2100 - RM-937, RM-939, RM-940</td>
</tr>
<tr>
<td class="ttl">&nbsp;</td>
<td class="nfo">HSDPA 850 / 900 / 1700 / 1900 / 2100 - RM-938</td>
</tr>
</tbody>

注意行<td class="ttl">&nbsp;</td>,它实际上不是新的规范类别,而是前一个的继续。所以,理想情况下它会进入前一个。

问题是在HTML的另一部分(定义主要类别Battery时),有这样的代码:

<tbody><tr>
<th rowspan="4" scope="row">Battery</th>
<td class="ttl">&nbsp;</td>
<td class="nfo">Non-removable Li-Ion 3400 mAh battery (BV-4BW)</td>
</tr><tr>
<td class="ttl"><a href="glossary.php3?term=stand-by-time">Stand-by</a></td>
<td class="nfo">Up to 768 h (2G) / Up to 768 h (3G)</td>
</tr><tr>
</tbody>

正如您所看到的,它以一个空的<td>开头,而这个不应该转到前一个。

我不知道如何解决这个问题。

1 个答案:

答案 0 :(得分:0)

您基本上需要检查spec_key是否为空。在这种情况下,您应该将结果追加到之前的spec_key。这里唯一的问题是你应该留意&nbsp; charachter。以下是代码的略微更改版本:

results = {}
tables = html.css('#specs-list table')
tables.each do |table|
  category_key = table.css('th').text
  rows = table.css('tr')
  current_spec_key = nil
  category_results = {}
  rows.each do |row|
    spec_key = row.css('.ttl').text.gsub("\u00a0",' ').strip #replace &nbsp; with space
    spec_content = row.css('.nfo').text
    if spec_key.empty?
      category_results[current_spec_key] << ", #{spec_content}"
    else
      current_spec_key = spec_key
      category_results[current_spec_key] = spec_content
    end
  end
  results[category_key] = category_results
end