我在一个只有我发现的inner_html的for循环中解析时遇到了麻烦。我想在内容中再次使用XPath。我是ruby的新手,所以更好的解决方案就在桌面上。
#!/usr/bin/ruby -w
require 'rubygems'
require 'nokogiri'
page1 = Nokogiri::HTML(open('mycontacts.html'))
# Search for nodes by xpath
page1.xpath('//html/body/form/div[2]/span/table/tbody/tr').each do |row|
#puts a_tag.content
puts "new row"
row_html = row.inner_html
puts row_html
puts ""
name = row_html.xpath("/td[1]").text
puts "name is " + name
end
for循环中每行的输出类似于:
new row
<th>First Name</th>
<th>Last Name</th>
<th>Phone</th>
这是我得到的错误:
screen-scraper.rb:20:在block in <main>': undefined method
xpath'中#(NoMethodError)
我想解析每个tr并得到如下数据:Barney Rubble,Fred Flintstone
<table>
<tbody>
<tr>
<th>First Name</th>
<th>Last Name</th>
</tr>
<tr>
<td>Fred</td>
<td>Flintstone</td>
</tr>
<tr>
<td>Barney</td>
<td>Rubble</td>
</tr>
</tbody>
</table>
我愿意接受建议。我认为只解析for循环中的inner_html更容易,但是如果有更容易的方法来获取for循环中的节点,那也可以。
...谢谢
答案 0 :(得分:1)
您可以修复它而不是使用name = row_html.xpath("/td[1]").text
,使用name = Nokogiri::HTML(row_html).xpath("/td[1]").text
。如果你分享了你的完整HTML,那么有一种很好的技巧。
Nokogiri::HTML(row_html)
会为您提供课程Nokogiri::HTML::Document
的实例。现在#xpath
,#css
和#search
所有方法都是Nokogiri::HTML::Document
类的实例方法。
考虑到如果您的inner_html
生成了您提供的HTML
表格,那么您可以将其想象如下。
我测试了代码,并希望它会给你结果:
require "nokogiri"
doc = Nokogiri::HTML(<<-eohl)
<table>
<tbody>
<tr>
<th>First Name</th>
<th>Last Name</th>
</tr>
<tr>
<td>Fred</td>
<td>Flintstone</td>
</tr>
<tr>
<td>Barney</td>
<td>Rubble</td>
</tr>
</tbody>
</table>
eohl
doc.css("table > tbody > tr"). each do |nd|
nd.children.each{|i| print i.text.strip," " unless i.text.strip == "" }
print "\n"
end
# >> First Name Last Name
# >> Fred Flintstone
# >> Barney Rubble
现在看看#inner_html
给出了什么,哪个会回答你为什么你有没有这样的方法错误:
require "nokogiri"
doc = Nokogiri::HTML(<<-eohl)
<table>
<tbody>
<tr>
<th>First Name</th>
<th>Last Name</th>
</tr>
<tr>
<td>Fred</td>
<td>Flintstone</td>
</tr>
<tr>
<td>Barney</td>
<td>Rubble</td>
</tr>
</tbody>
</table>
eohl
doc.search("table > tbody > tr"). each do |nd|
p nd.inner_html.class
end
# >> String
# >> String
# >> String
答案 1 :(得分:1)
问题是由row_html
获得的Nokogiri::XML::Node#inner_html
只是一个字符串。
要再次调用xpath
,必须先使用Nokogiri::HTML(row_html)
使用Nokogiri再次解析字符串。
更好的方法是从不首先拨打inner_html
,将row
保留为Nokogiri::XML::Node
,然后拨打row.xpath(...)
。
例如,使用您提供的表格并输出您想要的内容:
page1.xpath('//html/body/form/div[2]/span/table/tbody/tr').each do |row|
puts "#{row.children[0].text} #{row.children[1].text}"
end
答案 2 :(得分:1)
...我注意到Firebug会产生一些与Nokogiri(或它的依赖项)不兼容的xpath表达式。我对Chrome的Debug XPath输出感到好运。
Firebug或浏览器的许多其他XPath输出的问题是,在生成XPath并合成<tbody>
标记时,它们遵循HTML规范,即使原始源没有。 XPath反映了这一点。
我们将原始HTML传递给Nokogiri进行解析,以及错误的XPath,Nokogiri找不到<table><tbody><tr>
链。
这是一个例子。从这个HTML开始:
<html>
<body>
<table>
<tr>
<td>
foo
</td>
</tr>
</table>
</body>
</html>
将其保存到文件并在Firefox,Chrome或Safari中打开,然后查看来源,并在Firebug或其等效文件中查看。
你会看到这样的东西,来自Firefox:
<table>
<tbody><tr>
<td>
foo
</td>
</tr>
</tbody></table>
要解决此问题,请不要依赖浏览器生成的XPath,并通过在文本编辑器中仅查看 RAW HTML来确认表的结构。 “查看源代码”选项对某些内容非常有用,但如果您发现任何<tbody>
个代码是可疑的,请转而使用编辑器进行检查。
此外,您不需要整个标记链来到达内部标记。相反,在路上寻找一些有助于找到目标节点的地标。如今,大多数HTML网页都在重要标记中包含class
和id
个参数。 ID参数特别好,因为它们必须是唯一的。如果存在唯一的其他参数,那么这些参数也可以工作。
有时您不会在您想要的标签之前找到识别标签,但其中嵌入了一些内容。然后,找到该嵌入式标签并逐步升级链,直到找到所需内容。使用XPath你可以使用..
(父),但是使用CSS你必须依赖Nokogiri :: XML :: Node的parent
方法,因为Nokogiri和CSS不支持父选择器(尚未)。