我有以下HTML:
<table width="100%" border="0" cellpadding="6" cellspacing="1">
<tbody>
<tr>
<td bgcolor="#ffd204" width="40%" nowrap=""><b>Tracking Number:</b></td>
<td bgcolor="#ffffff" width="60%" nowrap="">C123456789012345</td>
</tr>
<!-- ...there could be additional table rows here... -->
<tr>
<td bgcolor="#ffd204" width="40%" nowrap=""><b>Deliver To:</b></td>
<td bgcolor="#ffffff" width="60%" nowrap="">ANYWHERE, NY</td>
</tr>
</tbody>
</table>
比如说,我需要提取ANYWHERE, NY
数据。我怎么用Nokogiri呢?或者是否有更好的东西来遍历这种没有任何CSS选择器来搜索的东西?
答案 0 :(得分:8)
由于我们没有要使用的CSS类,id
属性或其他语义标记,我们会在本文档中寻找可能不会更改的内容来锚定我们的搜索。在这种情况下,我怀疑“Deliver To:”标签总是在我们想要的td之前。所以:
require 'nokogiri'
html = # Fetch either from http via open-uri's open() or from file via IO.read()
doc = Nokogiri.HTML(html)
delivery = doc.at_xpath '//td[preceding-sibling::td[b="Deliver To:"]]/text()'
p delivery.content
#=> "ANYWHERE, NY"
XPath表达式说:
//
- 在任何级别,td
- 找到一个名为td
[…]
- 但仅限......
preceding-sibling::
- 它有一个先前的兄弟td
- 这是一个名为td
[…]
- 但仅限......
b
- 它有一个名为b
="Deliver To:"
- 其文字内容等于此字符串/text()
- 然后找到td
的子文本节点。因为我们使用at_xpath
而不是xpath
,所以Nokogiri返回它可以找到的第一个匹配节点 - 在这种情况下碰巧是该td的唯一子文本节点 - 而不是数组节点
如果<td>
可以有标记,例如<td…>ANYWHERE,<br>NY</td>
,您可以修改表达式以省略尾随/text()
(这样您只选择<td>
本身)然后使用text
方法获取其中的组合可见文本。
答案 1 :(得分:0)
鉴于您不介意进行一些预处理,您可以这样做:
lookup = {}
c = Nokogiri::HTML(open("http://..."))
c.search("tr").each do |tr|
cells = tr.search("td")
lookup[cells.first.text.gsub(':', '')] = cells.last.text
end
puts lookup["Tracking Number"]
我没有测试该代码,因此可能存在一些语法问题。