如何使用带有nokogiri的XPath解析for循环中的inner_html



我在解析只有我发现的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 method0生成您提供的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页面在重要标签中都有classid参数。ID参数尤其重要,因为它们必须是唯一的。如果存在其他唯一的参数,这些参数也可以工作。

有时候你不会在你想要的标签前面找到一个识别标签,但是它里面有一些东西。然后,找到嵌入的标签,沿着链条往上走,直到找到你想要的东西。使用XPath您可以使用..(父元素),但是使用CSS您必须依赖Nokogiri::XML::Node的parent方法,因为Nokogiri和CSS(目前)不支持父元素的选择器。

相关内容

  • 没有找到相关文章

最新更新