所以,我正在使用一个碰巧只返回XML的API,这很糟糕。我想做的是为从 API 返回的每条记录创建一个数据库条目,但我不确定如何做。
返回的 XML 非常庞大,并且其中有很多空格字符......这正常吗?下面是一些 XML 的示例。
<!-- ... -->
<attribute name="item_date">May 17, 2011</attribute>
<attribute name="external_url">http://missionlocal.org/2011/05/rain-camioneta-part-i/</attribute>
<attribute name="source" id="2478">Mission Loc@l</attribute>
<attribute name="excerpt"></attribute>
</attributes>
</newsitem>
<newsitem
id="5185807"
title="Lost Chrome messenger PBR bag and contents (marina / cow hollow)"
url="http://sf.everyblock.com/lost-and-found/by-date/2011/5/17/5185807/"
location_name="Van Ness and Filbert"
schema="lost-and-found"
schema_id="7"
pub_date="May 17, 2011, 12:15 p.m."
longitude="-122.424129925"
latitude="37.7995100578"
>
<attributes>
<attribute name="item_date">May 17, 2011</attribute>
<attribute name="external_url">http://sfbay.craigslist.org/sfc/laf/2386709187.html</attribute>
</attributes>
</newsitem>
<newsitem
id="5185808"
title="Plywood Update: Dumplings & Buns Aims To Be "Beard Papa Of Chinese Buns""
url="http://sf.everyblock.com/news-articles/by-date/2011/5/17/5185808/"
location_name="2411 California Street"
schema="news-articles"
schema_id="5"
pub_date="May 17, 2011, 12:15 p.m."
longitude="-122.434000442"
latitude="37.7888985667"
>
<attributes>
<attribute name="item_date">May 17, 2011</attribute>
<attribute name="external_url">http://sf.eater.com/archives/2011/05/17/dumplings_buns_aims_to_be_beard_papa_of_chinese_buns.php</attribute>
<attribute name="source" id="2155">Eater SF</attribute>
<attribute name="excerpt"></attribute>
</attributes>
</newsitem>
<newsitem
id="5185809"
title="Freebies: This week, Piazza D'Angelo (22 Miller..."
url="http://sf.everyblock.com/news-articles/by-date/2011/5/17/5185809/"
location_name="22 Miller"
schema="news-articles"
schema_id="5"
pub_date="May 17, 2011, 12:15 p.m."
longitude="-122.408894997"
latitude="37.7931966922"
>
<attributes>
<attribute name="item_date">May 17, 2011</attribute>
<attribute name="external_url">http://sf.eater.com/archives/2011/05/17/freebies_24.php</attribute>
<attribute name="source" id="2155">Eater F</attribute>
<attribute name="excerpt"></attribute>
<!-- ... -->
有什么想法吗?
这不是非常有效的XML。这是 XML 的某种转义字符串表示形式,可能是控制台输出。它似乎也不完整。除此之外,它是相当正常的XML。下面是一个较小的摘录,未转义和格式化:
<newsitem
id="5185807"
title="Lost Chrome messenger PBR bag and contents (marina / cow hollow)"
url="http://sf.everyblock.com/lost-and-found/by-date/2011/5/17/5185807/"
location_name="Van Ness and Filbert"
schema="lost-and-found"
schema_id="7"
pub_date="May 17, 2011, 12:15 p.m."
longitude="-122.424129925"
latitude="37.7995100578">
<attributes>
<attribute name="item_date">May 17, 2011</attribute>
<attribute name="external_url">http://sfbay.craigslist.org/sfc/laf/2386709187.html</attribute>
</attributes>
</newsitem>
您只需要确定要提取并放入数据库的内容,并让它驱动您的数据库设计决策。您是否需要多个关系完整的模型,或者您只关心数据的子集?
XML 可以有空格,而不会影响它所包含的数据的质量。一个好的解析器,即你应该如何处理XML,不会关心,并且会让你访问数据,无论是否有空格。
Nokogiri 是我的最爱,现在似乎是 Ruby 事实上的标准。它非常易于使用,但您必须学习如何告诉它您想要哪些节点。
为了帮助您入门,这里有一些术语:
- 节点是标签被解析后的术语。
- 节点具有属性,可以使用
node_var['attribute']
访问这些属性。 - 可以使用
node_var.text
或node_var.content
或node_var.inner_text
访问节点文本。 - NodeSet 基本上是一个节点数组。
-
at
返回与您提供给分析器的访问器匹配的第一个节点。%
是一个别名。 -
search
返回与您提供给分析器的访问器匹配的节点的 NodeSet。/
是一个别名。
以下是我们如何解析 XML 片段的方法:
require 'nokogiri'
xml =<<EOT
<newsitem
id="5185807"
title="Lost Chrome messenger PBR bag and contents (marina / cow hollow)"
url="http://sf.everyblock.com/lost-and-found/by-date/2011/5/17/5185807/"
location_name="Van Ness and Filbert"
schema="lost-and-found"
schema_id="7"
pub_date="May 17, 2011, 12:15 p.m."
longitude="-122.424129925"
latitude="37.7995100578">
<attributes>
<attribute name="item_date">May 17, 2011</attribute>
<attribute name="external_url">http://sfbay.craigslist.org/sfc/laf/2386709187.html</attribute>
</attributes>
</newsitem>
EOT
doc = Nokogiri::XML(xml)
doc.at('newsitem').text # => "n n May 17, 2011n http://sfbay.craigslist.org/sfc/laf/2386709187.htmln n"
(doc % 'attribute').content # => "May 17, 2011"
doc.at('attribute[name="external_url"]').inner_text # => "http://sfbay.craigslist.org/sfc/laf/2386709187.html"
doc.at('newsitem')['id'] # => "5185807"
newsitem = doc.at('newsitem')
newsitem['title'] # => "Lost Chrome messenger PBR bag and contents (marina / cow hollow)"
attributes = doc.search('attribute').map{ |n| n.text }
attributes # => ["May 17, 2011", "http://sfbay.craigslist.org/sfc/laf/2386709187.html"]
attributes = (doc / 'attribute').map{ |n| n.text }
attributes # => ["May 17, 2011", "http://sfbay.craigslist.org/sfc/laf/2386709187.html"]
所有访问都使用 CSS,就像您在编写网页时使用的那样。它更简单,通常也更清晰,但Nokogiri也支持XPath,它非常强大,可以让你将大量处理卸载到底层libXML2库,这将运行得非常快。
Nokogiri 与 Ruby 的 Open-URI
配合得很好,所以如果你从网站检索 XML,你可以这样做:
require 'open-uri'
require 'nokogiri'
doc = Nokogiri::HTML(open('http://www.example.com'))
doc.to_html.size # => 2825
这就是解析 HTML,Nokogiri 也擅长,但 XML 的过程是一样的,只需将 Nokogiri::HTML
替换为 Nokogiri::XML
即可。
另请参阅"如何避免在抓取时联接节点中的所有文本"。