Ruby和Nokogiri解析表?

时间:2013-12-29 09:43:10

标签: html ruby nokogiri

这是我的HTML:

<tbody><tr><th>SHOES</th></tr>
  <tr>
    <td>
      Shoe 1 <br>shoe 2<br> shoe3 <br>
    </td>
  </tr>
</tbody>

这是我的代码:

nodes = page.css("tr").select do |el|
  el.css('th').text =~ /SHOES/
end

nodes.each do |value|
  puts value.css("td").text
end

我希望获得值shoe 1shoe 2shoe 3,但没有输出。我怀疑<tr></tr>之间有一个额外的<tr><th>SHOES</th></tr>。或者<br>是罪魁祸首?

还有其他结构,如:

<tr>
  <th>SHOES</th>
  <td>NBA</td>
</tr>

我得到了所需的输出"NBA"

我做错了什么?

我有两种结构:

Name1: value
Name1: value2

以上将给出:

<tr>
<th>Name1</th>
<td>Value</td>
</tr>

但有时它是:

Name:
value
value2
value3

所以HTML是:

<tbody><tr><th>Name</th></tr>
<tr>
<td>value<br>value2<br> ....</td>

2 个答案:

答案 0 :(得分:3)

在HTML中,表由行组成。当您按这些行进行迭代时,只有其中一行是标题。虽然逻辑上你看到了主体行和标题行之间的关系,但对于HTML(因此对于Nokogiri)来说,没有。

如果您想要的是获取具有特定标题的单元格的每个值,您可以做的是计算特定列,然后从那里获取值。

将此HTML用作源

html = '<tbody><tr><th>HATS</th><th>SHOES</th></tr>
  <tr>
    <td>
      hat 1 <br>hat 2<br> hat3 <br>
    </td>
    <td>
      Shoe 1 <br>shoe 2<br> shoe3 <br>
    </td>
  </tr>
  </tbody>'

然后我们按照在表格的第一行中获取右边的位置

page = Nokogiri::HTML(html)

shoes_position = page.css("tr")[0].css('th').find_index do |el|
  el.text =~ /SHOES/
end

然后,我们在每个其他行中找到该位置的s,并从该

中获取文本
shoes_tds = page.css('tr').map {|row| row.css('td')[shoes_position] }.compact
shoes_names = shoes_tds.map { |td| td.text }

我使用compact来删除nil值,因为第一行(带标题的那一行)没有td,因此返回nil

答案 1 :(得分:0)

你可以用css到达那里:

td = doc.at('tr:has(th[text()=SHOES]) + tr td')
td.children.map{|x| x.text.strip}.reject(&:empty?)
#=> ["Shoe 1", "shoe 2", "shoe3"]

但也许将它与xpath混合起来更好:

td.search('./text()').map{|x| x.text.strip}
#=> ["Shoe 1", "shoe 2", "shoe3"]