JSON richtig auslesen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Corvinus
User
Beiträge: 8
Registriert: Mittwoch 18. Oktober 2023, 19:04

Hallo!

Ich bin gerade dabei, die Kurse von Bitcoin historisch auszulesen und sie in eine Grafik auszugeben. Allerdings scheitere ich kläglich an der Ausführung.

Die Historischen Daten habe ich von dieser Webseite, welche ich auslesen möchte: https://api.coinbase.com/v2/prices/BTC- ... d=all_time

Das lese ich wie folgt aus:

Code: Alles auswählen

import requests
import pandas as pd
import matplotlib.pyplot as plt
import json

response = requests.get("https://api.coinbase.com/v2/prices/BTC-USD/historic?period=all_time")

daten = response.json()
print(daten['data']['prices']['price'])
Leider funktioniert das nicht. Bis zur zweiten Ebene also ['data']['prices'] funktioniert es, aber wenn ich mir nur die 3. Ebene ['data']['prices']['price'] ausgeben lassen möchte, kriege ich das nicht hin. Wie kann ich das Problem lösen, wenn ich nur die Price angezeigt lassen möchte?

Vielen Dank für die Unterstützung
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Welche Fehlermeldung erhältst Du?
Was ist daten['data']['prices'] für eine Datentyp? Welche Operationen kann man darauf ausführen?
Corvinus
User
Beiträge: 8
Registriert: Mittwoch 18. Oktober 2023, 19:04

Hallo!

Die Fehlermeldung lautet:

print(daten['data']['prices']['price'])
TypeError: list indices must be integers or slices, not str
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Jetzt fehlt nur noch die Antwort auf die weiteren Fragen.
Corvinus
User
Beiträge: 8
Registriert: Mittwoch 18. Oktober 2023, 19:04

Auf deine anderen Fragen habe ich mangels wissen leider keine Antwort.

Ich weis nur, das JSON der Webseite ist so aufgebaut:

Code: Alles auswählen

{"data":{"base":"BTC","currency":"USD","prices":[{"price":"28285.65","time":"1697691640"},{"price":"28288.34","time":"1697691630"},{"price":"28290.59","time":"1697691620"},
{"price":"28291.14","time":"1697691610"},{"price":"28294.34","time":"1697691600"},{"price":"28294.33","time":"1697691590"},{"price":"28297.38","time":"1697691580"},{"price":"28290.08","time":"1697691560"},
{"price":"28290.07","time":"1697691550"},{"price":"28290.08","time":"1697691540"},{"price":"28284.59","time":"1697691530"},{"price":"28283.7","time":"1697691520"},{"price":"28290.07","time":"1697691510"},
{"price":"28290.08","time":"1697691490"},{"price":"28286.01","time":"1697691480"},{"price":"28285.44","time":"1697691470"},{"price":"28285.72","time":"1697691460"},{"price":"28281.1","time":"1697691450"},
{"price":"28278.44","time":"1697691440"},{"price":"28275.01","time":"1697691420"},{"price":"28275.01","time":"1697691410"},{"price":"28275","time":"1697691400"},{"price":"28275.01","time":"1697691390"},
{"price":"28275.01","time":"1697691380"},{"price":"28275.7","time":"1697691370"},{"price":"28275","time":"1697691350"},
Und ich will hier nur das Feld "price" auslesen. und ich hab keine Ahnung, wie ich das einzelne Feld extrahieren kann.

Und im Endergebnis will ich "price" und "time" in einen Graphen plotten. Nur ich kriege immer Fehlermeldungen, wenn ich die (einzelnen) Daten rausziehen will, und ich hab keine Ahnung warum.
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Was erwartest Du als Ergebnis von daten['data']['prices']['price']?
Den Typ eines Objekts bekommt man über

Code: Alles auswählen

print(type(daten['data']['prices']))
Corvinus
User
Beiträge: 8
Registriert: Mittwoch 18. Oktober 2023, 19:04

ich erwarte mir, dass ich als Ergebnis beispielsweise von {"data":{"base":"BTC","currency":"USD","prices":[{"price":"28285.65","time":"1697691640"} den wert 28285.65 erhalte, von mir aus auch in einem array, wo alle werte von price drinstehen. ich will halt nur den wert der variable price auslesen, sodass ich dann später mit den darin enthaltenen werten arbeiten kann.

Wenn ich print type eingebe, erhalte ich als ergebnis: <class 'list'>
imonbln
User
Beiträge: 191
Registriert: Freitag 3. Dezember 2021, 17:07

Corvinus hat geschrieben: Mittwoch 18. Oktober 2023, 19:57 TypeError: list indices must be integers or slices, not str
Ich Spoiler mal,

Die Fehlermeldung: "TypeError: list indices must be integers or slices, not str" und der Aufbau der JSON Struktur sollte dir sagen, dass daten['data']['prices'] eine Liste ist. Welche dictionaries enthält.
Corvinus
User
Beiträge: 8
Registriert: Mittwoch 18. Oktober 2023, 19:04

ok, und wie mach ich das jetzt, dass ich die daten rausziehen kann? um das gehts mir.
Benutzeravatar
noisefloor
User
Beiträge: 4194
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

per Indexzugriff. Ein JSON-Array wird in Python zu einer Liste.

Bei verschachtelten Strukturen muss man genau hinschauen, wo eine eckige und wo eine geschweifte Klammer steht. Deine Struktur nach Python übertragen ist: Dict -> Dict -> Liste -> Dict.

Gruß, noisefloor
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Um was es Dir geht, ist hier klar, und ich versuche Dir den Weg zu zeigen, wie Du da hinkommst.
Du weißt also jetzt, dass es sich um eine Liste handelt.
Dann lies mal in dem Tutorial Deiner Wahl nach, wie man mit Listen arbeitet.
Corvinus
User
Beiträge: 8
Registriert: Mittwoch 18. Oktober 2023, 19:04

boah, das ist komplizierter als ich dachte.

also das dict->dict->liste->dict hat mir mal geholfen.

für einen einzelnen wert schreibe ich jetzt wie folgt:

Code: Alles auswählen

preis = daten['data']['prices'][0]['price']
jetzt muss ich nur noch rausfinden, wie ich alle in der liste ansprechen kann.
imonbln
User
Beiträge: 191
Registriert: Freitag 3. Dezember 2021, 17:07

Was würdest du denn mit der Liste machen, wenn sie nicht in einen Dict gekapselt wäre?

Du könntest ja zum Beispiel so was schreiben,

Code: Alles auswählen

preise = daten['data']['prices']
Dann wäre die Variable preise: list->dict, könntest du da jedes Element ansprechen?
Corvinus
User
Beiträge: 8
Registriert: Mittwoch 18. Oktober 2023, 19:04

das habe ich auch schon versucht, das wäre hier aber, soweit ich das verstanden habe, nur eine abgekürzte version.
da hab ich zwar alle daten drin, kann aber die einzelnen elemente ohne das listenelement nicht direkt ansprechen.

mein script schaut jetzt so aus:

Code: Alles auswählen

import requests
import pandas as pd
import matplotlib.pyplot as plt
import json
from datetime import datetime

# Make a request to the Coinbase API to get the historical price data for Bitcoin
response = requests.get("https://api.coinbase.com/v2/prices/BTC-USD/historic?period=all_time")

daten = json.loads(response.text)

preis = daten['data']['prices']
anzahl=len(preis) 
print("Die Liste hat soviele Einträge: ", anzahl)

for i in range(0,anzahl):
    zeit_orig=preis[i]['time']
    zeit=int(zeit_orig)
    zeit=datetime.fromtimestamp(zeit)
    preiss=preis[i]['price']
    print('Preis: ',preiss,' Zeit: ', zeit)

so hab ich mal alle zeit und werte am bildschirm. mein nächster schritt, ist das irgendwie in ein pandas dataframe zu übertragen, damit ich das graphisch mit matplotlib plotten kann.
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Mit welchem Tutorial lernst Du eigentlich Python?

Über einen Index iteriert man nicht. Um Operatoren setzt man Leerzeichen, der besseren Lesbarkeit wegen.
Würde man für die Preise den richtigen Variabennamen wählen `preise` müßte man nicht ein falsch geschriebenes `preiss` für einen einzelnen Preis benutzen.
Man muß aber auch nicht jedes einzelne Zwischenergebnis an eine Variable binden.
`requests` kennt die Methode json, damit wird das Lesen einfacher.

Code: Alles auswählen

import requests
from datetime import datetime as DateTime

# Make a request to the Coinbase API to get the historical price data for Bitcoin
response = requests.get("https://api.coinbase.com/v2/prices/BTC-USD/historic?period=all_time")
response.raise_for_status()
daten = response.json()

preise = daten['data']['prices']
for eintrag in preise:
    zeit = DateTime.fromtimestamp(int(eintrag['time']))
    preis = eintrag['price']
    print('Preis:', preis, 'Zeit:', zeit)
Für pandas kannst Du Dir das Leben einfach machen und direkt aus der Liste `daten['data']['prices']` ein Dataframe erzeugen lassen:

Code: Alles auswählen

prices = pd.DataFrame(daten["data"]["prices"])
Corvinus
User
Beiträge: 8
Registriert: Mittwoch 18. Oktober 2023, 19:04

Oh vielen Dank,

genau so hatte ich mir das vorgestellt. ich habs jetzt auch mit dem Graph-Plotten hinbekommen.

Ich habe übrigens kein Tutorial. Ich habe oftmals eine Idee, und dann versuche ich sie umzusetzen. Meistens hilft mir Google dabei, aber in manchen Fällen komme ich damit nicht weiter und brauche dann Hilfe von jemand, der wirklich was davon versteht.
Benutzeravatar
noisefloor
User
Beiträge: 4194
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

na, aber immer auf fremde Hilfe angewiesen zu sein ist halt auch doof. Im Falle von Python solltest du zumindest mal das offizielle Tutorial durchgearbeitet haben: https://docs.python.org/3/tutorial/index.html . Dann sollten auch die Frage hier im Thread geklärt sein, weil Umgang mit Dictionaries und Liste sind die absoluten Basics bei Python.

Gruß, noisefloor
Antworten