Получить информацию из таблицы с Nokogiri?

0

Я пытаюсь получить информацию о спецификациях для этого сайта:

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 Network в моем хеше.

Это сложная для меня роль:

<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 (при определении батареи основной категории) есть этот код:

<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>, и этот не следует переходить к предыдущему.

Я не уверен, как это решить.

  • 0
    Я думаю, что вы должны проверить spec_key и, если он пуст, объединить spec_content с содержимым предыдущего spec_key .
  • 1
    Вам нужно предоставить краткий / маленький пример HTML, который вы пытаетесь проанализировать. Не просите нас перейти на этот сайт и обобщить его для вас.
Показать ещё 2 комментария
Теги:
parsing
nokogiri

1 ответ

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
  • 0
    Никос, хороший подход. Однако при этом у меня возникнет проблема в разделе «Аккумулятор». Обратите внимание, что он начинается с пустого <td>, и если бы я поместил его в предыдущий, это было бы неправильно ..
  • 0
    Это зависит от того, как вы хотите представить дело без ключа спецификации. В простом случае, когда у вас все в порядке с чем-то вроде {"" => " if spec_key.empty? && !current_spec_key.nil? ..."}, вы можете изменить первый, if на if spec_key.empty? && !current_spec_key.nil? , Если вам нужна специальная обработка первого раза, когда вы найдете пустой ключ, вы можете изменить первый, if на if current_spec_key.nil? && spec_key.empty? и затем добавьте elsif и else для двух других случаев.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню