Как разобрать xml из запросов? - PullRequest
0 голосов
/ 24 января 2020

Я посмотрел несколько других ответов, но не смог найти решение, которое бы сработало для меня.

Вот мой полный код, который вы можете запустить без ключа API:

import requests

r = requests.get('http://api.worldbank.org/v2/country/GBR/indicator/NY.GDP.MKTP.KD.ZG')

Если я печатаю r.text, я получаю строку, которая начинается с

'\ufeff<?xml version="1.0" encoding="utf-8"?>\r\n<wb:data page="1" pages="2" per_page="50" total="60" sourceid="2" lastupdated="2019-12-20" xmlns:wb="http://www.worldbank.org">\r\n  <wb:data>\r\n    <wb:indicator id="NY.GDP.MKTP.KD.ZG">GDP growth (annual %)</wb:indicator>\r\n    <wb:country id="GB">United Kingdom</wb:country>\r\n    <wb:countryiso3code>GBR</wb:countryiso3code>\r\n    <wb:date>2019</wb:date>\r\n`

и продолжается некоторое время.

Один из способов получить то, что я хотел бы из этого ( что, насколько я понимаю, крайне не рекомендуется) использовать регулярное выражение:

import regex

import pandas as pd
import re

pd.DataFrame(
    re.findall(
        r"<wb:date>(\d{4})</wb:date>\r\n    <wb:value>((?:\d\.)?\d{14})", r.text
    ),
    columns=["date", "value"],
)

Что такое "правильный" способ анализа этого вывода xml? Моя конечная цель - создать DataFrame со столбцами date и value, такими как

    date    value
0   2018    1.38567356958762
1   2017    1.89207703836381
2   2016    1.91815510596298
3   2015    2.35552430595799
...

Ответы [ 3 ]

1 голос
/ 24 января 2020

Как насчет следующего:

Расшифровать ответ:

decoded_response = response.content.decode('utf-8')

Преобразовать в json:

response_json = json.loads(json.dumps(xmltodict.parse(decoded)))

Читать в DataFrame:

pd.read_json(response_json) 

Тогда вам просто нужно поиграть с востоком и прочим (документы: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_json.html)

0 голосов
/ 24 января 2020

Полный код, который я использовал (основываясь на превосходном ответе Омри):

import xmltodict
import json
import pandas as pd

r = requests.get("http://api.worldbank.org/v2/country/GBR/indicator/NY.GDP.MKTP.KD.ZG")
decoded_response = r.content.decode("utf-8")

response_json = json.loads(json.dumps(xmltodict.parse(decoded_response)))

pd.DataFrame(response_json["wb:data"]["wb:data"])[["wb:date", "wb:value"]].rename(
    columns=lambda x: x.replace("wb:", "")
)

, что дает

    date    value
0   2019    None
1   2018    1.38567356958762
2   2017    1.89207703836381
3   2016    1.91815510596298
4   2015    2.35552430595799
...
0 голосов
/ 24 января 2020

Вы можете использовать ElementTree API (как описано здесь )

import requests
from xml.etree import ElementTree

response = requests.get('http://api.worldbank.org/v2/country/GBR/indicator/NY.GDP.MKTP.KD.ZG')

tree = ElementTree.fromstring(response.content)

print(tree)

Но вам придется изучить структуру, чтобы получить то, что вы хотите.

...