Hallo,
ich möchte gerne mit python und requests dateien von
https://garmin-connect-weight-api.onrender.com/ runterladen.
Damit bekomme ich dann .fit-Dateien, die ich auf Garmin hochladen kann.
Da kann man folgendes importieren:
Garmin-Aktivitätsdateien (TCX-, FIT- oder GPX-Format)
Fitbit®-Daten zu Gesundheit oder Aktivitäten (XLS-, XLSX- oder
CSV-Format).
Ich kann die Daten von meiner Waage/App (Waage: Fitleap; App: Fitdays)
als .xlsx exportieren
(Beitrag "csv parsen kryptische Symbole"), aber dies ist
dennoch ein anderes Format.
mein Problem ist aber, dass das mit dem post-request bei mir nicht so
ganz funktioniert
Chandler B. schrieb:> mein Status-Code ist 405.
Method not allowed. Die statt dessen zulässigen Request-Methoden stehen
im Allow-Header der 405-Antwort.
Chandler B. schrieb:> ich möchte gerne mit python und requests dateien von> https://garmin-connect-weight-api.onrender.com/ runterladen.> Damit bekomme ich dann .fit-Dateien, die ich auf Garmin hochladen kann.> [...]> mein Problem ist aber, dass das mit dem post-request bei mir nicht so> ganz funktioniert>
> [...]> Hat jemand einen tip woran das liegt?
Ja, an zwei Dingen: erstens POSTest DU auf den flashcen URL, deswegen
kommt dort korrekterweise ein 405 ("Method not allowed"). Wenn ich das
ECMAScript unten auf der Seite richtig lese, ist "/weight" der korrekte
Endpunkt.
Auf "/weight" kommt jedoch das zweite Ding zum Tragen, Du POSTest
nämlich gar kein JSON, wenngleich Dein Header das behauptet. In Wahrheit
sendest Du Daten im MIME-Typ "application/x-www-form-urlencoded" -- das
macht requests nämlich so, wenn "data" ein Dictionary übergeben wird.
Der Server sieht also den Body 'weight=80.1&percentFat=20' anstelle des
ausweislich des genannten ECMAScript gewünschten JSON-Formats
'{"weight":80.1,"percentFat":20}'.
Dein "Content-type"-Header behauptet also einen anderen Content-type als
Du sendest. Der Server wird dann versuchen, Deinen Body in
"application/x-www-form-urlencoded" mit einem JSON-Parser zu dekodieren.
Das schlägt natürlich fehl und deswegen bekommst Du einen HTTP/500
"Internal Server Error" zurück. So weit, so korrekt.
Wenn Du "application/json" senden willst, wie es dieser Service
anscheinend erwartet, dann mußt Du Deine Daten entsprechend formatieren,
zum Beispiel mit der Funktion "dumps" aus den Standardmodul "json" --
das macht "requests" nicht automatisch für Dich, nur weil Du den
Content-type gesetzt hast.
Ein wohlerzogener Server könnte möglicherweise auch Daten in
"application/x-www-form-urlencoded" verarbeiten, wenn der Header korrekt
gesetzt wäre. Aber ich würde mich an Deiner Stelle eher nicht darauf
verlassen. :-)
Franko S. schrieb:> Dein Contentlength stimmt nicht,
Das ist aber nicht der Punkt.
>
1
> --data '{"weight":80.1, "percentFat":20}'
2
>
Der Punkt ist hier, daß Du einen korrekten JSON-String schickst. Darum
klappt es bei Dir. Der TO schickt aber keinen JSON-String, und das
schlägt fehl.
Ein T. schrieb:> Franko S. schrieb:>> Dein Contentlength stimmt nicht,>> Das ist aber nicht der Punkt.>>>> --data '{"weight":80.1, "percentFat":20}'>>>> Der Punkt ist hier, daß Du einen korrekten JSON-String schickst. Darum> klappt es bei Dir.
Und seine fasche Content-length weglasse. Setzt man diese funktioniert
es nämlich nicht mehr obwohl der Rest korrekt ist also liegt es auch an
seinem falschen Content-Length-Angabe.
> Der TO schickt aber keinen JSON-String, und das schlägt fehl.
ja, u.a. Was das Pythondignens reponse da noch vorher drann
rumflickwerkt weiss auch keiner.
Deshalb nimmt man erst mal curl und schaut ob es formal richtig ist,
wenn es dann immer noch nicht geht, liegt es an der der request-lib von
Python oder was auch immer man da verwendet.
Content-Length selber setzen ist eh meistens überflüssig wenn man ne lib
nutzt, die erzeugt das automatisch richtig, vor allem wenn man das noch
encoded, packt,... ausser man fummelt da ohne lib herum, von einem Mc
heraus wo man http noch selber zusammenklöppelt weil der MC zu
schwach/wenig Speicher hat.
Franko S. schrieb:> Ein T. schrieb:>> Franko S. schrieb:>>> Dein Contentlength stimmt nicht,>>>> Der Punkt ist hier, daß Du einen korrekten JSON-String schickst. Darum>> klappt es bei Dir.>>> Und seine fasche Content-length weglasse. Setzt man diese funktioniert> es nämlich nicht mehr obwohl der Rest korrekt ist also liegt es auch an> seinem falschen Content-Length-Angabe.
Ja, äh... nein. Es ist nicht seine falsche Content-Length-Angabe,
sondern es ist leider Deine falsche Content-Length-Angabe, wie wir
gleich sehen.
> Deshalb nimmt man erst mal curl und schaut ob es formal richtig ist,
... und baut dabei einen neuen Fehler ein, der mit dem ursprünglichen
leider nichts zu tun hat. War gut gemeint von Dir, aber... :-)
> wenn es dann immer noch nicht geht, liegt es an der der request-lib von> Python oder was auch immer man da verwendet.
Ach, weißt Du, das "requests"-Paket in Python ist weit verbreitet und
gut getestet, da würde ich mal vermuten, daß es seine Sache richtig
macht. Und siehe da: das tut es dann auch.
Das "requests"-Modul setzt die Content-Length nämlich vollkommen
korrekt, und zwar unabhängig davon, ob und wie sie im Header angegeben
wurde. Der Request
1
requests.post(
2
"http://localhost:2000",
3
data=json.dumps({'foo': 'bar', 'num': 2}),
4
headers={"Content-Length": "234"}
5
)
schickt die korrekte Content-Length von 24:
1
POST /asdf
2
User-Agent: python-requests/2.31.0
3
Accept-Encoding: gzip, deflate, br
4
Accept: */*
5
Connection: keep-alive
6
Host: localhost:2000
7
Content-Length: 21
8
9
{"foo":"bar","num":2}
Beispiel-Server und -Client habe ich angehängt, wenn es jemand selbst
ausprobieren möchte. Viel Spaß! :-)