Nokogiri XML Builder在抓取HTML时创建意外输出

时间:2011-01-22 03:40:10

标签: ruby xml nokogiri

我对Ruby和编程世界都很陌生,所以请耐心等待。

我的目标是刮取表格,然后将数据保存到XML文件中。我编写的简单脚本可以完成这两件事。我遇到的问题是XML的保存方式。它与我以前看到的XML不匹配。

我翻遍了很多例子,教程和论坛,但尚未找到解决方案。

我对有关从表中获取数据的更好方法的任何建议持开放态度,特别是因为前三列都是我真正需要的。 HELP !!!

这是我的剧本:

require 'nokogiri'
require 'open-uri'

url = "http://www.covers.com/pageLoader/pageLoader.aspx?page=
/data/nba/team/pastresults/2010-2011/team404085.html"
doc = Nokogiri::HTML(open(url))

builder = Nokogiri::XML::Builder.new do |xml|
  xml.root {
    xml.items {
       doc.css('.data').each do |o|
        xml.item_content = o
       end
    }
  }
end

File.open('ATL.xml','w'){|f| f.write builder.to_xml}

puts "Scrape Completed."  

无论是保存到.xml文件还是在Ruby屏幕上打印,XML都是这样的:

<?xml version="1.0"?>
<root>
  <items>
    <item_content=>&lt;table cellpadding="2" cellspacing="1" class="data"&gt;
&lt;tr class="datahead"&gt;
&lt;td width="11%"&gt;Date&lt;/td&gt;&#xD;
    &lt;td width="21%"&gt;Vs&lt;/td&gt;&#xD;
    &lt;td width="18%"&gt;Score&lt;/td&gt;&#xD;
    &lt;td width="27%"&gt;Type&lt;/td&gt;&#xD;
    &lt;td width="13%"&gt;ATL Line&lt;/td&gt;&#xD;
    &lt;td width="10%"&gt;O/U&lt;/td&gt;&#xD;
  &lt;/tr&gt;
&lt;tr class="datarow"&gt;
&lt;td&gt;&#xD;
        01/18/11&lt;/td&gt;&#xD;
      &lt;td&gt;&#xD;
        @ &lt;a href="/pageLoader/pageLoader.aspx?page=/data/nba/team/
team404171.html"&gt;Miami&lt;/a&gt;&#xD;
        &lt;/td&gt;&#xD;
      &lt;td&gt;&#xD;
        W &lt;a href="/pageLoader/pageLoader.aspx?page=/data/nba/
results/2010-2011/boxscore795345.html"&gt;&#xD;
        93-89&lt;/a&gt; (OT)&lt;/td&gt;&#xD;
      &lt;td&gt;&#xD;
        Regular Season&lt;/td&gt;&#xD;
      &lt;td&gt;&#xD;
        W 5.5&lt;/td&gt;&#xD;
      &lt;td&gt;&#xD;
        U 194&lt;/td&gt;&#xD;
    &lt;/tr&gt;

上面的代码只是一个片段,因为有多行。 (共44个)
这样做的最佳方法是什么?

1 个答案:

答案 0 :(得分:3)

目前还不清楚你想要什么作为你的输出;你想要XML中包含的原始HTML,还是HTML的内容?将来,当您包含一个您想要的示例以及问题示例时,它会很有帮助。让我们解决这两个问题。首先,我们可以更简单地重现您的问题:

require 'nokogiri'
doc = Nokogiri::XML <<ENDXML
  <root>
    <p class="foo">42</p>
    <p class="bar">99</p>
    <p class="foo">17</p>
  </root>
ENDXML

builder = Nokogiri::XML::Builder.new do |xml|
  xml.items {
    doc.css('.foo').each{ |o| xml.item_content = o }
  }
end    
puts builder.to_xml
#=> <?xml version="1.0"?>
#=> <items>
#=>   <item_content=>&lt;p class="foo"&gt;42&lt;/p&gt;</item_content=>
#=>   <item_content=>&lt;p class="foo"&gt;17&lt;/p&gt;</item_content=>
#=> </items>

如果您只想在HTML中使用HTML节点的内容,并且假设您不希望等号成为标记名称的一部分,那么:

builder = Nokogiri::XML::Builder.new do |xml|
  xml.items {
    doc.css('.foo').each{ |o| xml.item_content( o.text ) }
  }
end
puts builder.to_xml
#=> <?xml version="1.0"?>
#=> <items>
#=>   <item_content>42</item_content>
#=>   <item_content>17</item_content>
#=> </items>

另一方面,如果您确实想要XML中的原始HTML,但不想要所有实体,那么将其设为CDATA块:

builder = Nokogiri::XML::Builder.new do |xml|
  xml.items {
    doc.css('.foo').each{ |o| xml.item_content{ xml.cdata o } }
  }
end
puts builder.to_xml
#=> <?xml version="1.0"?>
#=> <items>
#=>   <item_content><![CDATA[<p class="foo">42</p>]]></item_content>
#=>   <item_content><![CDATA[<p class="foo">17</p>]]></item_content>
#=> </items>

XML CDATA block允许您使用通常为XML标记保留的字符,而无需将它们表示为字符实体。