Seite 1 von 1
Verwertung von JSON response
Verfasst: Dienstag 26. Januar 2016, 15:05
von Haolong
Guten Tag,
ich versuche mir Python anzueignen und erledige dazu Übungsaufgaben aus einem "Buch". Nun wird von mir verlangt eine API in mein Programm einzubinden und zwar:
http://api.open-notify.org/astros.json
Habe jetzt einige Zeit im Internet geforscht, komme aber immer noch nicht auf einen einheitlichen Strang, wie man dieses Thema angeht. Unter anderem habe ich versucht den Post:
viewtopic.php?f=1&t=37811&p=289985&hili ... rl#p289985 nachzuvollziehen, jedoch ohne Erfolg.
Ich arbeite in Pycharm mit Python 3.
Versucht habe ich das ganze mit:
Code: Alles auswählen
import urllib.request
import json
url = "http://api.open-notify.org/astros.json"
response = urllib.request.urlopen(url).read()
print(response)
data = json.load(response)
der print Befehl gibt mir:
Code: Alles auswählen
b'{\n "message": "success", \n "number": 6, \n "people": [\n {\n "craft": "ISS", \n "name": "Mikhail Kornienko"\n }, \n ...
wenn ich diesen Salat jedoch mit json.load umwandeln möchte, bekomme ich die Fehlermeldung:
Code: Alles auswählen
AttributeError: 'bytes' object has no attribute 'read'
Könnte mir jemand erklären, was ich Schritt für Schritt zu tun habe, um mit den Code der Seite etwas anzufangen?
p.s: das ist hier meiner erster Post, deswegen weß ich nicht wie man den Code in einer schöneren Ansicht darstellt.
Gruß,
Hao
Re: Verwertung von JSON response
Verfasst: Dienstag 26. Januar 2016, 15:18
von BlackJack
@Haolong: `json.load()` will keine Bytes sondern ein Dateiobjekt mit einer `read()`-Methode. Deshalb genau diese Fehlermeldung. Also entweder darfst Du nicht selber `read()` auf dem Ergebnis von `urlopen()` aufrufen sondern *das* `json.load()` übergeben, oder Du muss `json.loads()` verwenden (und gegebenfalls die Bytes vorher in eine Zeichenkette dekodieren).
Ich persönlich verwende ja gerne die `requests`-Bibliothek, da kann man JSON-Antworten schon dekodiert abfragen.
Edit: Ich sehe gerade das der Beitrag auf den Du Dich beziehst gar kein `read()` macht, das hast Du dazugeschrieben.
Edit2: Mit `requests` (Python 2, aber das ist egal weil die API bei Python 3 gleich ist):
Code: Alles auswählen
In [3]: requests.get('http://api.open-notify.org/astros.json').json()
Out[3]:
{u'message': u'success',
u'number': 6,
u'people': [{u'craft': u'ISS', u'name': u'Mikhail Kornienko'},
{u'craft': u'ISS', u'name': u'Scott Kelly'},
{u'craft': u'ISS', u'name': u'Sergey Volkov'},
{u'craft': u'ISS', u'name': u'Yuri Malenchenko'},
{u'craft': u'ISS', u'name': u'Timothy Kopra'},
{u'craft': u'ISS', u'name': u'Timothy Peake'}]}
Re: Verwertung von JSON response
Verfasst: Dienstag 26. Januar 2016, 15:23
von /me
Du hast zwei Probleme. Zuerst einmal bekommst du ein bytes-Objekt zurück aus dem du noch einen String machen musst. Dafür musst du wissen, wie die Daten kodiert worden sind. Ich nehme in meinem Beispielcode einfach mal UTF-8 an, aber Encodings zu raten ist grundsätzlich eine blöde Idee.
Dein zweites Problem ist, dass du
json.load statt
json.loads verwendest. Schau dir mal an, was für Parameter die beiden Funktionen jeweils haben möchten.
Folgendes Codefragment sollte dir einen Einstieg geben.
Code: Alles auswählen
response = urllib.request.urlopen(url).read()
data = json.load(response.decode('UTF-8'))
Re: Verwertung von JSON response
Verfasst: Dienstag 26. Januar 2016, 16:01
von Haolong
Mit dem read() habe ich herumexperimentiert. Ohne read() bekomme ich dieses Objekt zurück:
Ist das gar kein JSON response? Muss ich ein anders Modul nehmen?
Code: Alles auswählen
response = urllib.request.urlopen(url).read()
data = json.load(response.decode('UTF-8'))
damit hat es leider auch nicht geklappt
Code: Alles auswählen
AttributeError: 'HTTPResponse' object has no attribute 'decode'
Wenn wir jetzt mal meinen Code völlig vergessen, wie würdet ihr an das Problem herangehen?
Edit: jetzt habe ich es noch mit dem "requests"-Modul ausprobiert und das klappt super

Re: Verwertung von JSON response
Verfasst: Dienstag 26. Januar 2016, 16:10
von /me
Die angegebene Exception entspricht nicht dem gezeigten Code. Das kann nur kommen wenn du das read() vergessen hast.
Re: Verwertung von JSON response
Verfasst: Dienstag 26. Januar 2016, 16:10
von BlackJack
@Haolong: Fehlermeldung und Code passen nicht zusammen. Da würde wieder die Fehlermeldung mit dem `read`-Attribut kommen, weil auch Zeichenketten keine solche Methode haben.
Von `urlopen()` bekommst Du ein Objekt das die HTTP-Anwort modelliert, also die Header und unter anderem eine Methode um die Daten, die vom Server kommen, zu lesen: `read()`. Entweder gibt man dieses Objekt an `json.load()`, denn das erwartet etwas was eine `read()`-Methode hat, oder man liest die Daten selber mit `read()`, dekodiert die gelesenen Bytes in eine Zeichenkette und übergibst die `json.loads()`. Man beachte den kleinen aber wichtigen Unterschied zwischen `load()` und `loads()`!
Re: Verwertung von JSON response
Verfasst: Dienstag 26. Januar 2016, 16:31
von Haolong
Code: Alles auswählen
import json
import urllib.request
url = "http://api.open-notify.org/astros.json"
response = urllib.request.urlopen(url).read()
data = json.load(response.decode('UTF-8'))
print(data)
ergibt diese Meldung;
1:1 aus meinem Pycharm kopiert, stimmt was mit meinen Modulen nicht ?
Auch wenn ich noch nicht voll hinter das thema read() load() und loads() gestiegen bin, kann ich nun mit derm requests Modul weiter machen. Danke schonmal dafür.
Re: Verwertung von JSON response
Verfasst: Dienstag 26. Januar 2016, 16:57
von Sirius3
@Haolong: wie BlackJack schon geschrieben hat, es muß
Code: Alles auswählen
response = urllib.request.urlopen(url).read()
data = json.loads(response.decode('UTF-8'))
oder
Code: Alles auswählen
response = urllib.request.urlopen(url)
data = json.load(response)
heißen.
Re: Verwertung von JSON response
Verfasst: Dienstag 26. Januar 2016, 17:01
von Haolong
ok sorry, mit loads() funktioniert es tatsächlich

Re: Verwertung von JSON response
Verfasst: Freitag 29. Januar 2016, 10:05
von Haolong
Habe nun meine letzte Aufgabe gut durch das "requests" Modul lösen können. Bei der nächsten Aufgabe gibt es jedoch schon wieder Probleme
Von
https://www.flickr.com/services/feeds/d ... os_public/ soll ich mir Bilder mit einem bestimmten Tag anzeigen lassen. Durch
https://api.flickr.com/services/feeds/p ... ormat=json bekomme ich im Browser eine JSON-Rückmeldung.
In Python requeste ich mit:
Code: Alles auswählen
import requests
url = "https://api.flickr.com/services/feeds/photos_public.gne"+"?format=json"
data = requests.get(url)
print(data)
Rückmeldung:
Wenn ich das ganze jedoch mit .json() umwandeln möchte:
bekomme ich die Fehlermeldung:
Traceback (most recent call last):
File "C:/Users/Haolong/PycharmProjects/Programmier Aufgaben/Aufgaben Skripte/Aufgabe 49.py", line 9, in <module>
data = requests.get(url).json()
File "C:\Users\Haolong\AppData\Roaming\Python\Python35\site-packages\requests\models.py", line 808, in json
return complexjson.loads(self.text, **kwargs)
File "C:\UsersHaolong\AppData\Local\Programs\Python\Python35-32\lib\json\__init__.py", line 319, in loads
return _default_decoder.decode(s)
File "C:\Users\Haolong\AppData\Local\Programs\Python\Python35-32\lib\json\decoder.py", line 339, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "C:\Users\Haolong\AppData\Local\Programs\Python\Python35-32\lib\json\decoder.py", line 357, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Ich kann damit leider wenig anfangen. Habe auch die anderen bereits genannten Methoden von diesem Thread ausprobiert, aber immer stoße ich auf Fehler.
Hoffe ihr könnt mir das Thema nochmal kurz erklären.
Gruß,
Hao
Re: Verwertung von JSON response
Verfasst: Freitag 29. Januar 2016, 10:21
von Dav1d
Wenn du dir
https://api.flickr.com/services/feeds/p ... ormat=json anschaust, am Anfang ist ein JS-Callback: `jsonFlickrFeed`. Der ist kein valides JSON, es gibt sicher in der API eine Option um das abzudrehen.
-> Geht tatsächlich
https://api.flickr.com/services/feeds/p ... callback=1
Re: Verwertung von JSON response
Verfasst: Freitag 29. Januar 2016, 10:49
von Haolong
Danke für die Hilfe. Nun kann ich per .json() den response verwerten. Ab und zu bekomme ich den Fehler (in unterschiedlichen lines):
File "C:\Users\Haolong\AppData\Local\Programs\Python\Python35-32\lib\json\decoder.py", line 355, in raw_decode
obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Invalid \escape: line 145 column 550 (char 11242)
Der lässt sich jedoch mit ner while Schleife und try - except umgehen.
Re: Verwertung von JSON response
Verfasst: Freitag 29. Januar 2016, 11:12
von Haolong
ich merke, dass der workaround doch nicht so toll ist, da es sehr lange dauern kann, bis ich eine gültige Rückmeldung bekomme. Warum ist sie manchmal valid und manchmal nicht? Muss ich mit dem response noch etwas machen bevor ich .json() verwende?
Re: Verwertung von JSON response
Verfasst: Freitag 29. Januar 2016, 13:58
von Dav1d
Du kannst wahrscheinlich vom JSONDecoder erben und ihn dazu bringen, dass er die Escapes akzeptiert (wahrscheinlich \x00 escapes).
Re: Verwertung von JSON response
Verfasst: Freitag 29. Januar 2016, 20:26
von BlackJack
Ich hab's gerade mal ausprobiert und das JSON hat \'-Escapes die nicht der JSON-Spezifikation entsprechen und an den Stellen wo ich sie gefunden habe (innerhalb von in "-Eingefassten Zeichenketten), auch völlig unnötig wären, falls sie denn erlaubt wären.
Re: Verwertung von JSON response
Verfasst: Montag 1. Februar 2016, 09:09
von Haolong
bedeutet das, ich kann den Response nicht ordentlich verwerten, da er nicht ordentlich erstellt wurde? Gibt es einen einfachen Weg die Escapes zu umgehen, oder muss ich mir den response in einem anderen Format ausgeben lassen?
Re: Verwertung von JSON response
Verfasst: Montag 1. Februar 2016, 14:55
von BlackJack
@Haolong: Du könntest diese fehlerhaften Escape-Sequenzen ersetzen und dann auf dem Ergebnis davon `json.loads()` aufrufen.