Мне нужно преобразовать загрузку XML из Wordpress в 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/"
>
И в файле сотни <item>
s, каждый из них с сотнями полей.
Пример одного:
<item>
<title>MockTitle</title>
<link>https://mock.url.io/?post_type=mock&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>
...
Мой код может легко извлекать такие элементы, как title
и pubDate
, но я не знаю, как я могу сделать это для поиска по 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...
Привет! Спасибо @JackFleeting. Да, я мог бы использовать его. Не могли бы вы привести мне быстрый пример или направить меня в правильном направлении для исследования, как бы я поступил с lxml
? Мне как бы нужно доставить как можно скорее, и время исследований сейчас очень ценно :)
Используя упрощенную версию вашего xml и lxml с xpath:
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&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&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
МОЙ БОГ! Удивительный. С очень небольшими правками это работает. Я пошел на сверхподробный тангенс, извлекая текст всех meta_keys и meta_values, и заархивируя их в словарь, а затем выполняя поиск. Это намного лаконичнее. Изменения, которые я должен был внести в код решения, для тех, у кого может быть такой же вопрос: - Мне пришлось использовать doc = etree.parse("filename.xml)
, потому что я извлекал из файла. - В логике поиска пришлось заменить , namespaces=nsmap2
на , namespaces = ns
@Lanski Да, последняя была опечаткой, которую я тем временем отредактировал. В любом случае, рад, что это сработало для вас! Если мы закончили, не забудьте принять ответ, пожалуйста.
Доступен ли вам lxml? Если да, то это можно легко сделать.