【问题标题】:XML to Pandas DF with namespaces - Python带有命名空间的 XML 到 Pandas DF - Python
【发布时间】:2020-12-09 20:01:49
【问题描述】:

我需要将从 Wordpress 下载的 XML 转换为 Pandas DF 以进行一些数据分析。

XML 是自动生成的,并且有一些命名空间:

<rss version="2.0"
    xmlns:excerpt="http://wordpress.org/export/1.2/excerpt/"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:wp="http://wordpress.org/export/1.2/"
>

并且该文件有数百个&lt;item&gt;s,每个&lt;item&gt;s 都有数百个字段。 一个例子:

<item>
        <title>MockTitle</title>
        <link>https://mock.url.io/?post_type=mock&#038;p=992</link>
        <pubDate>Fri, 30 Oct 2020 20:47:53 +0000</pubDate>

        (...)

        <wp:postmeta>
            <wp:meta_key><![CDATA[_customer_user]]></wp:meta_key>
            <wp:meta_value><![CDATA[0]]></wp:meta_value>
        </wp:postmeta>
        
        <wp:postmeta>
            <wp:meta_key><![CDATA[_payment_method]]></wp:meta_key>
            <wp:meta_value><![CDATA[paypal]]></wp:meta_value>
        </wp:postmeta>

        <wp:postmeta>
            <wp:meta_key><![CDATA[_payment_method_title]]></wp:meta_key>
            <wp:meta_value><![CDATA[PayPal]]></wp:meta_value>
        </wp:postmeta>

        <wp:postmeta>
            <wp:meta_key><![CDATA[_customer_ip_address]]></wp:meta_key>
            <wp:meta_value><![CDATA[1.1.1.15]]></wp:meta_value>
        </wp:postmeta>

        <wp:postmeta>
            <wp:meta_key><![CDATA[_customer_user_agent]]></wp:meta_key>
            <wp:meta_value><![CDATA[Mock Info about the agent]]></wp:meta_value>
        </wp:postmeta>

        (...)
</item>
<item>
...

我的代码可以轻松提取titlepubDate 之类的元素,但我不知道如何通过wp:meta_key 搜索并实际提取出与该键对应的wp:meta_value。为了能够使用我想要的特定信息创建数据框,我错过了这一点。

到目前为止,这是我的代码:

import pandas as pd
import xml.etree.ElementTree as et 

xtree = et.parse("data.xml")
xroot = xtree.getroot()

for item in xroot: 
    order_number = item.find("./title").text
    date = item.find("./pubDate").text

#Don't know how to access the different wp:postmeta's and search by wp:meta_key...

【问题讨论】:

  • 您可以使用 lxml 吗?如果是这样,它可以很容易地完成。
  • 嘿!谢谢@JackFleeting。是的,我可以使用它。你能给我一个简单的例子或指导我正确的方向来研究我将如何使用lxml 来解决这个问题吗?我有点需要尽快交付,现在研究时间非常宝贵:)

标签: python xml pandas wordpress


【解决方案1】:

使用 xml 的简化版本,以及带有 xpath 的 lxml:

rss = """<rss version="2.0"
    xmlns:excerpt="http://wordpress.org/export/1.2/excerpt/"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:wp="http://wordpress.org/export/1.2/"
>
<items>
<item>
        <title>MockTitle</title>
        <link>https://mock.url.io/?post_type=mock&#038;p=992</link>
        <pubDate>Fri, 30 Oct 2020 20:47:53 +0000</pubDate>
        <wp:postmeta>
            <wp:meta_key><![CDATA[_customer_user]]></wp:meta_key>
            <wp:meta_value><![CDATA[0]]></wp:meta_value>
        </wp:postmeta>        
        <wp:postmeta>
            <wp:meta_key><![CDATA[_payment_method]]></wp:meta_key>
            <wp:meta_value><![CDATA[paypal]]></wp:meta_value>
        </wp:postmeta>
</item>
<item>
        <title>MockTitle2</title>
        <link>https://mock2.url.io/?post_type=mock&#038;p=992</link>
        <pubDate>Fri, 30 Oct 2220 20:47:53 +0000</pubDate>
        <wp:postmeta>
            <wp:meta_key><![CDATA[_customer_user]]></wp:meta_key>
            <wp:meta_value><![CDATA[02]]></wp:meta_value>
        </wp:postmeta>        
        <wp:postmeta>
            <wp:meta_key><![CDATA[_payment_method]]></wp:meta_key>
            <wp:meta_value><![CDATA[paypal2]]></wp:meta_value>
        </wp:postmeta>
</item>
</items>
</rss>"""

from lxml import etree
doc = etree.XML(rss)
ns = { (k if k else "xx"):(v) for k, v in doc.xpath('//namespace::*') }

#searching, for example, for "_payment_method"

for company in doc.xpath("//wp:meta_key[.='_payment_method']/following-sibling::wp:meta_value/text()", namespaces=ns):
    print(company)

输出:

paypal
paypal2

【讨论】:

  • 天哪!惊人的。通过非常小的编辑,这是有效的。我进行了一个超级详细的切线,提取所有元键和元值的文本,并将它们压缩到字典中,然后进行搜索。这要简洁得多。对于那些可能有相同问题的人,我必须对解决方案的代码进行更改: - 我必须使用doc = etree.parse("filename.xml),因为我是从文件中提取的。 - 在搜索逻辑中,我不得不将, namespaces=nsmap2更改为, namespaces = ns
  • @Lanski 是的,最后一个是我临时编辑的错字。无论如何,很高兴它对你有用!如果我们完成了,请不要忘记接受答案。
猜你喜欢
  • 1970-01-01
  • 2021-10-24
  • 1970-01-01
  • 2011-01-05
  • 2015-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多