Seite 1 von 1

API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Samstag 11. Januar 2020, 12:11
von Glare
Hallo, bin recht neu bei Python und versuche mich gerade daran eine XML Datai aus dem Internet auszulesen.

Der Aufruf per requests funktioniert soweit, nur komme ich leider nicht mit dem auslesen der XML Datei klar und würde mich über Hilfestellung freuen.

Code: Alles auswählen

import requests
from xml.etree import ElementTree as ET

starturl = "http://webservice.rakuten.de/merchants/orders/getOrders"
param = dict(key="123456789a123456789a123456789a12")
resp = requests.get(url=starturl, params=param)

tree = ET.parse(resp.text)
root = tree.getroot()
Dies ist eine Testumgebung und gibt eine Bestellung aus. Mit print(resp.text) kann ich mir nun auch die komplette XML Datai ausgeeben lassen. Aber ich verstehe einfach nicht wie ich nun an einzelne Punkte komme, z.B. Kundendaten, Artikel, ...
Habe mir einige Seiten angeschaut und daher auch nicht sicher ob ich nun ElementTree, lxml oder SAX verwenden soll/muß.

Hoffe ihr habt ein paar Tipps für mich.

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 07:29
von Jankie
XML Dateien kannst du mit BeautifulSoup4 parsen.

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 08:10
von Sirius3
@Jankie: mit BeautifulSoup hast Du nur einen anderen Zugriff auf die Daten. Bei XML ist normalerweise ElementTree oder das äquivalent aus lxml die erste Wahl. Dann mit Zugriff auf die Elemente per XPath.

@Glare: kannst Du näher beschreiben, wo Du genau Probleme hast, was Du lesen willst und wie die XML-Datei aufgebaut ist?

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 12:13
von Glare
Sirius3 hat geschrieben: Montag 13. Januar 2020, 08:10 @Glare: kannst Du näher beschreiben, wo Du genau Probleme hast, was Du lesen willst und wie die XML-Datei aufgebaut ist?
Hallo Sirius3,

ich habe Probleme zu verstehen wie ich mit ElementTree an die Daten aus der XML komme.
Also ein kleiner Tipp wie ich z.B. an orders->order->invoice_no komme würde mir schon sehr helfen um alles andere auszulesen.

Hier der Link zur XMLhttps://webservice.rakuten.de/merchants ... 3456789a12

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 12:44
von __blackjack__
@Glare: Wo genau ist denn das Problem und was hast Du schon ausprobiert, und wie wich das dann von Deinem erwarteten Ergebnis ab?

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 12:57
von Jankie
@Sirius3: Ist nur die Art des Zugriffes anders oder wieso ist ElementTree dafür besser geeignet? Bisher habe ich alles mit BS4 und dem lxml Parser gemacht und finde das auch eigentlich sehr übersichtlich.

Hier mal als BS4 Beispiel:

Code: Alles auswählen

from bs4 import BeautifulSoup
import requests

URL = "https://webservice.rakuten.de/merchants/orders/getOrders?key=123456789a123456789a123456789a12"
HEADERS = {"User-Agent":"Dein User Agent"}

page = requests.get(URL, headers=HEADERS)
soup = BeautifulSoup(page.content, "lxml")

invoice_number = soup.find("invoice_no").get_text()

print(invoice_number)

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 13:18
von __blackjack__
@Jankie: Das würde ich mal sagen ist falsch weil das so für HTML ist, also sehr lax mit dem XML umgeht und da sogar Ergebnisse bringt wenn das XML kaputt ist. BS nimmt man eigentlich wegen der ganzen Abkürzungen für HTML die mit BS gehen weil BS HTML ”kennt”. Bei XML ist der Teil aber nicht sinnvoll. Da würde man einfach die ElementTree-API aus der Standardbibliothek mit der Untermenge von XPath verwenden die das implementiert, oder `lxml` und dann XPath.

Edit: Nur "invoice_no" wäre mir zu unsicher, es gibt doch einen schönen, eindeutigen Pfad zu der Information.

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 13:27
von Jankie
Hatte vorher auch den ganzen "Pfad" genommen, also soup.find("orders").find("order").find("invoice_no").get_text(), dachte aber das wäre überflüssig wenn invoice_no sowieso im gesamten XML nur einmal vorkommt.

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 13:39
von Sirius3
@Jankie: die vielen find sind trotzdem falsch, weil sie ja auch über alle Ebenen hinweg suchen. Man will wirklich den Pfad /oders/oder/invoice_no gehen, weil das einfach im sichersten ist.

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 13:41
von __blackjack__
@Jankie: Weisst Du ja nicht das es nur einmal vorkommt. Bei XML hat man ja eine viel festere Struktur bei den Dokumenten, so das ein Tag auch woanders vorkommen kann und nicht verwechselt werden kann, weil da ja strukturell dann ein anderer Pfad hin führt. Und alleine drei solche `find()`-Aufrufe zu machen spricht doch schon gegen BS und für XPath.

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 14:02
von Glare
__blackjack__ hat geschrieben: Montag 13. Januar 2020, 12:44 @Glare: Wo genau ist denn das Problem und was hast Du schon ausprobiert, und wie wich das dann von Deinem erwarteten Ergebnis ab?
ich bin nach diesem Tutorial gegangen: https://riptutorial.com/de/python/examp ... lementtree

Code: Alles auswählen

import xml.etree.ElementTree as ET
import requests

starturl = "http://webservice.rakuten.de/merchants/orders/getOrders"
param = dict(key="123456789a123456789a123456789a12")
resp = requests.get(url=starturl, params=param)

tree = ET.parse(resp.text)
root = tree.getroot()

print(root[0][1].text)
Letzte Zeile ist natürlich nicht der richtige Pfad, wäre aber schon froh irgendeinen Eintrag aus der xml Datei zu erhalten. Anstelle kommt aber folgende Fehlermeldung:
Traceback (most recent call last):
File "s:/python/xml.py", line 1, in <module>
import xml.etree.ElementTree as ET
File "s:\python\xml.py", line 1, in <module>
import xml.etree.ElementTree as ET
ModuleNotFoundError: No module named 'xml.etree'; 'xml' is not a package

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 14:05
von Jankie
@__blackjack__: Wäre die Umsetzung mit ET und XPath so richtig?

Code: Alles auswählen

import xml.etree.ElementTree as ET


tree = ET.parse('getOrders.xml')
root = tree.getroot()

for order in root.findall("./orders/order/invoice_no"):
    print(order.text)

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 14:12
von __blackjack__
@Jankie: Kann man so machen. Ich würde `order` anders nennen, denn es steht ja nicht für ein <order>- sondern für ein <invoice_no>-Element.

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 14:59
von Sirius3
@Glare: Du hast in Deinem eigenen Verzeichnis eine Datei xml.py angelegt, die das Standardpaket xml überdeckt. Nenne diese Datei um und lösche eventuell vorhandene xml.pyc-Dateien.

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 15:19
von Glare
Sirius3 hat geschrieben: Montag 13. Januar 2020, 14:59 @Glare: Du hast in Deinem eigenen Verzeichnis eine Datei xml.py angelegt, die das Standardpaket xml überdeckt. Nenne diese Datei um und lösche eventuell vorhandene xml.pyc-Dateien.
Ok, Datei umbenannt, damit wäre der Fehler schonmal weg :-)


Nun kommt folgende Fehlermeldung wenn ich
tree = ET.parse(resp.text)
verwende:
Traceback (most recent call last):
File "s:/python/blablablub.py", line 8, in <module>
tree = ET.parse(resp.text)
File "C:\Program Files\Python38\lib\xml\etree\ElementTree.py", line 1202, in parse
tree.parse(source, parser)
File "C:\Program Files\Python38\lib\xml\etree\ElementTree.py", line 584, in parse
source = open(source, "rb")
OSError: [Errno 22] Invalid argument: '<?xml ver...
Danach noch der komplette Inhalt der XML

Nehme ich eine lokale Datei, also
tree = ET.parse('getOrders.xml')
, dann funktioniert es.

Muß ich (resp.text) vorher noch bearbeiten?

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 15:44
von sparrow
Zum Programmieren gehört auch Dokumentation zu lesen und zu verstehen. .parse() erwartet laut Dokumentation einen Dateinamen, aus dem der Inhalt geparst wird. Du hast aber keine Datei, du hast einen String. Auf der verlinkten Dokumentationsseite steht auch eine Funktion um von einem String zu parsen.

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 15:47
von Glare
sparrow hat geschrieben: Montag 13. Januar 2020, 15:44 Zum Programmieren gehört auch Dokumentation zu lesen und zu verstehen. .parse() erwartet laut Dokumentation einen Dateinamen, aus dem der Inhalt geparst wird. Du hast aber keine Datei, du hast einen String. Auf der verlinkten Dokumentationsseite steht auch eine Funktion um von einem String zu parsen.
...source is a filename or file object...
Ich habe die Doku gelesen und für mich war es ein file object. Aber da habe ich mich wohl geirrt. Trotzdem danke für den Hinweis.

Re: API Abfrage per Requests, anschließende XML Auswertung

Verfasst: Montag 13. Januar 2020, 16:17
von __deets__
Es ist ja auch ein file Objekt. Oder Dateiname. Was es NICHT ist, ist XML als String. Und den hast du da reingeworfenen.