【问题标题】:basic xml parsing with Python使用 Python 进行基本的 xml 解析
【发布时间】:2014-07-20 14:44:28
【问题描述】:

我正在通过他们的 API 从 Flickr 提取图像数据,我打印的是几千个看起来像这样的 xml 对象:

<photo accuracy="15" context="0" dateupload="1398279194" farm="8" geo_is_contact="0" geo_is_family="0" geo_is_friend="0" geo_is_public="1" height_n="320" id="13986079375" isfamily="0" isfriend="0" ispublic="1" latitude="41.828482" license="0" longitude="-87.624506" owner="100231432@N02" pathalias="perspectivesschools" place_id="cF8n.mJTWrhYf0uBEw" secret="f46eef0b1d" server="7308" title="Sean Gallagher, Pulitzer Photojournalist visits MSA" url_n="https://farm8.staticflickr.com/7308/13986079375_f46eef0b1d_n.jpg" width_n="213" woeid="28297331" />
<photo accuracy="12" context="0" dateupload="1394558054" farm="4" geo_is_contact="0" geo_is_family="0" geo_is_friend="0" geo_is_public="1" height_n="213" id="13086071753" isfamily="0" isfriend="0" ispublic="1" latitude="51.451914" license="2" longitude="-0.122882" owner="96189004@N04" pathalias="" place_id="JYdWRftQUbMvFA" secret="265103ac38" server="3040" title="" url_n="https://farm4.staticflickr.com/3040/13086071753_265103ac38_n.jpg" width_n="320" woeid="13978" />
<photo accuracy="12" context="0" dateupload="1394558019" farm="8" geo_is_contact="0" geo_is_family="0" geo_is_friend="0" geo_is_public="1" height_n="213" id="13086343854" isfamily="0" isfriend="0" ispublic="1" latitude="51.451914" license="2" longitude="-0.122882" owner="96189004@N04" pathalias="" place_id="JYdWRftQUbMvFA" secret="a6858f84d2" server="7451" title="" url_n="https://farm8.staticflickr.com/7451/13086343854_a6858f84d2_n.jpg" width_n="320" woeid="13978" />

现在我想一次性提取属性“lat”和“long”的数据。以及另一个中属性“url_n”的数据。我怎样才能在 Python 中做到这一点?我没有解析 xml 数据的经验,也不知道从哪里开始。

非常感谢!

【问题讨论】:

  • etreeBeautifulSoup

标签: python xml python-2.7 xml-parsing


【解决方案1】:

使用 lxml

虽然 Python 中有多个与 XML 相关的包,包括。 stdlib 一,我更喜欢使用lxml,作为 它提供了我需要的所有东西(良好的 XPath 支持、模式验证等),我更喜欢保留数字 我使用的包很小。

对于来自 Flickr 的 xml 文档,解决方案可能如下所示

脚本flickr.py

from lxml import etree
xmllines = """
<photo accuracy="15" context="0" dateupload="1398279194" farm="8" geo_is_contact="0" geo_is_family="0" geo_is_friend="0" geo_is_public="1" height_n="320" id="13986079375" isfamily="0" isfriend="0" ispublic="1" latitude="41.828482" license="0" longitude="-87.624506" owner="100231432@N02" pathalias="perspectivesschools" place_id="cF8n.mJTWrhYf0uBEw" secret="f46eef0b1d" server="7308" title="Sean Gallagher, Pulitzer Photojournalist visits MSA" url_n="https://farm8.staticflickr.com/7308/13986079375_f46eef0b1d_n.jpg" width_n="213" woeid="28297331" />
<photo accuracy="12" context="0" dateupload="1394558054" farm="4" geo_is_contact="0" geo_is_family="0" geo_is_friend="0" geo_is_public="1" height_n="213" id="13086071753" isfamily="0" isfriend="0" ispublic="1" latitude="51.451914" license="2" longitude="-0.122882" owner="96189004@N04" pathalias="" place_id="JYdWRftQUbMvFA" secret="265103ac38" server="3040" title="" url_n="https://farm4.staticflickr.com/3040/13086071753_265103ac38_n.jpg" width_n="320" woeid="13978" />
<photo accuracy="12" context="0" dateupload="1394558019" farm="8" geo_is_contact="0" geo_is_family="0" geo_is_friend="0" geo_is_public="1" height_n="213" id="13086343854" isfamily="0" isfriend="0" ispublic="1" latitude="51.451914" license="2" longitude="-0.122882" owner="96189004@N04" pathalias="" place_id="JYdWRftQUbMvFA" secret="a6858f84d2" server="7451" title="" url_n="https://farm8.staticflickr.com/7451/13086343854_a6858f84d2_n.jpg" width_n="320" woeid="13978" />
"""

for line in xmllines.strip().splitlines():
    doc = etree.fromstring(line)
    urls = doc.xpath("/photo/@url_n")
    if urls:
        url = urls[0]
        print url
    else:
        print "---no attribute url_n was found---"

会输出:

$ python flickr.py
https://farm8.staticflickr.com/7308/13986079375_f46eef0b1d_n.jpg
https://farm4.staticflickr.com/3040/13086071753_265103ac38_n.jpg
https://farm8.staticflickr.com/7451/13086343854_a6858f84d2_n.jpg

【讨论】:

  • 它有效,谢谢!我设法用 minidom 解决了这个问题,但是在解析更大的数据集时由于某种原因代码中断了......
  • @loop_digga 欢迎您。我想,中断的代码是minidom,而不是lxml。由于minidom 在内存中完成所有工作,因此较大的文档可能会出现问题(即使您的问题显示了很多非常小的 XML 文档)。使用lxml,很少有选择如何使用有限的内存(使用iterparse 甚至使用SAX 解析)来处理大型(甚至无穷无尽的)文档。
  • 感谢您的补充说明!但实际上,这两个代码都与更大的数据集不同。现在尝试使用更大的数据并在打印 648 个 URL 后发生错误:'IndexError: list index out of range'。不知道发生了什么。
  • @loop_digga 很可能,&lt;photo ../&gt; xml 文档编号 649 没有“url_n”属性。我已经修改了答案来处理这个问题。
  • 你是对的!我显然在 minidom 代码中遇到了同样的问题。谢谢!
【解决方案2】:

使用正则表达式解析 XML 是 not a good idea。试试BeautifulSoup - 它不仅解析 XML,而且还具有轻松获取与所选对象及其属性相关的下一个/父级/等元素的功能。

使用示例:

from bs4 import BeautifulSoup
(...)
soup = BeautifulSoup(flickr_xml)
for photo in soup.find_all('photo'):
    print(photo.get('url_n'))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-12
    • 1970-01-01
    • 2021-02-19
    • 2010-12-17
    • 2013-07-18
    • 2019-09-27
    相关资源
    最近更新 更多