我在解析只有我发现的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。
我想解析每个tr并获得这样的数据:Barney粗石族,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循环中获得节点,那也可以。
谢谢…
您可以使用name = Nokogiri::HTML(row_html).xpath("/td[1]").text
而不是name = row_html.xpath("/td[1]").text
来修复它。不过,如果您与他人共享完整的HTML,则有一种很好的方法可以做到这一点。
Nokogiri::HTML(row_html)
将为您提供类Nokogiri::HTML::Document
的实例。现在#xpath
、#css
、#search
所有的方法都是Nokogiri::HTML::Document
类的实例方法。
考虑到如果您的block in <main>': undefined method
0生成您提供的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
给出了什么,它将回答你为什么会得到no such method错误:
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
问题是Nokogiri::XML::Node#inner_html
获得的row_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
…我注意到Firebug生成的一些xpath表达式不能很好地与Nokogiri(或其依赖项)一起工作。我有更好的运气与Chrome的Debug XPath输出
Firebug或浏览器的许多其他XPath输出的问题是,它们在生成XPath并合成<tbody>
标记时遵循HTML规范,即使原始源代码没有CC_21标记。XPath反映了这一点。
我们将原始HTML和错误的XPath一起传递给Nokogiri进行解析,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(目前)不支持父元素的选择器。