如何搜索“text”然后从找到的节点遍历DOM?

时间:2011-04-25 03:42:24

标签: ruby nokogiri

我有网页,我需要从中抓取一些数据。问题是,每个页面可能有也可能没有特定数据,或者它可能在DOM中具有高于或低于它的额外数据,并且没有CSS ID可以说。

通常我可以使用CSS ID或XPath来访问我正在寻找的节点。在这种情况下我没有这个选项。我要做的是搜索“标签”文本,然后在下一个<TD>节点中获取数据:

<tr> 
    <td><b>Name:</b></td> 
    <td>Joe Smith <small><a href="/Joe"><img src="/joe.png"></a></small></td> 
</tr>

在上面的HTML中,我会搜索:

doc.search("[text()*='Name:']")

在我需要的数据之前获取节点,但我不确定如何从那里导航。

3 个答案:

答案 0 :(得分:25)

next_element可能是您正在寻找的方法。

require 'nokogiri'

data = File.read "html.htm"

doc  = Nokogiri::HTML data

els  = doc.search "[text()*='Name:']"
el   = els.first

puts "Found element:"
puts el
puts

puts "Parent element:"
puts el.parent
puts

puts "Parent's next_element():"
puts el.parent.next_element

# Output:
#
# Found element:
# <b>Name:</b>
#
# Parent element:
# <td> 
#     <b>Name:</b>
# </td>
#
# Parent's next_element():
# <td>Joe Smith <small><a href="/Joe"><img src="/joe.png"></a></small>
# </td>

请注意,由于文本位于<b></b>标记内,因此您必须升级到找到的元素的父<td>)才能进入下一个兄弟。如果HTML结构不稳定,您必须找到<td>的第一个父级并从那里开始。

答案 1 :(得分:2)

require 'nokogiri'

html = '
<html>
  <body>
    <p>foo</p>
    this text
    <p>bar</p>
  </body>
</html>
'

doc = Nokogiri::HTML(html)
doc.at('p:contains("foo")').next_sibling.text.strip
=> "this text"

答案 2 :(得分:0)

您可以使用xpath的parent / following_sibling语法在单个语句中执行整个搜索:

>> require 'nokogiri' 
=> true   
>> html = <<HTML
<tr> 
    <td><b>Name:</b></td> 
    <td>Joe Smith <small><a href="/Joe"><img src="/joe.png"></a></small></td> 
</tr>
HTML
>> doc = Nokogiri::HTML(html)

>> doc.at_xpath("//*[text()='Name:']/../following-sibling::*").to_s
=> "<td>Joe Smith <small><a href=\"/Joe\"><img src=\"/joe.png\"></a></small>\n</td>"