Seite 1 von 1

String aus einem request.get extrahieren

Verfasst: Sonntag 30. Juni 2019, 19:19
von peko
Hallo zusammen,

um die Anzahl der Produkte im Vorratsraum im Keller zu sehen, möchte ich diese beim Einlagern identifizieren und in eine sqlite db eintragen.
Da ein Mitglied der Familie Probleme mit dem Treppensteigen hat, möchte ich das Prozedere vereinfachen und die Liste über eine Webseite
des RasPi ausgeben.
Der request klappt auch, nur komme ich nicht dahinter, wie ich aus dem Ergebnis nur die Zeile hinter "detailname=" extrahieren kann.
Den Teil bis zum Schlüsselwort "detailname=" bekomme ich noch weg, der Eintrag des Produktes wird mit einem "\n" abgeschlossen.
Wie kann ich diesen suchen, die Position herausfinden und ab da den Rest löschen.
Ich hab schon bei String- und Listenmanipulationen gesucht, aber nichts gefunden.

Hier mein bisheriger Versuch

Code: Alles auswählen

#!/usr/bin/python3

import requests
import re

req = requests.get("https://opengtindb.org/?ean=4000540000405&cmd=query&queryid=400000000")
print (req.text)
suche = re.findall(r"detailname=[^.;:!?]{2,}", req.text)
print (suche)
Nach was muss ich genau suchen, um den String hinter "detailname=" herauszufiltern
In diesem Fall: "Kölln Instant Flocken, 1er Pack (1x 250gr)"

Gruß peko

Re: String aus einem request.get extrahieren

Verfasst: Sonntag 30. Juni 2019, 21:02
von Sirius3
Irgendwie hatten wir das Problem schon einmal.
Das ist ein Datenformat, das zeilenweise Key-Value-Paare enthält, die in Gruppen eingeteilt sind, die durch `====` getrennt werden. Also mußt Du den Response (`req` ist eine komische Abkürzung, weil da ja gar kein q vorkommt, daher niemals Variablennamen ablürzen) zeilenweise durchgehen und mit z.b. partition in Key und Value aufspalten. Man würde dafür eine Funktion schreiben, die als Ergebnis eine Liste mit Wörterbüchern hat, wobei das erste Wörterbuch angibt, ob ein Fehler aufgetreten ist, was Du auch prüfen solltest.
Zwischen ›print‹ und öffnender Klammer kommt kein Leerzeichen.

Re: String aus einem request.get extrahieren

Verfasst: Sonntag 30. Juni 2019, 21:24
von peko
Hallo Sirius3,

vielen Dank erstmal.
Das mit dem key / value bekomme ich leider nicht mal Ansatzweise hin, da ich keinen Plan habe, wie ich es einlesen / abfragen soll.
Haben die Zeilenenden nicht ein "\n" hinten dran, denn "====" habe ich nirgends gesehen.

Das q kommt von request, das Leerzeichen ist eine Angewohnheit aus früheren PHP-Zeiten.
Ich versuche mich zu bessern ;-)

Re: String aus einem request.get extrahieren

Verfasst: Montag 1. Juli 2019, 05:00
von Sirius3
Ein Filehandle zeilenweise einzulesen und einen String am = zu splitten sind absolute Grundlagen.

Code: Alles auswählen

for line in lines:
    key, _, value = line.strip().partition('=')

Re: String aus einem request.get extrahieren

Verfasst: Montag 1. Juli 2019, 05:39
von snafu
Ich würde direkt alles parsen:

Code: Alles auswählen

dict(line.split('=') for line in response.text.splitlines() if '=' in line)
...und dann die Infos aus dem Dict nehmen, die ich benötige.

Re: String aus einem request.get extrahieren

Verfasst: Montag 1. Juli 2019, 06:18
von Sirius3
@snafu: das ist nicht ganz korrekt, weil der Response aus mehreren Blöcken besteht. `response` kennt `iter_lines`.

Re: String aus einem request.get extrahieren

Verfasst: Montag 1. Juli 2019, 08:05
von snafu
Bei iter_lines() werden aber Bytes geliefert, die man noch konvertieren müsste. Und dass im text Attribut Blöcke geliefert werden, wäre mir neu...

Re: String aus einem request.get extrahieren

Verfasst: Montag 1. Juli 2019, 10:36
von __blackjack__
@snafu: Das fällt auf die Nase wenn der Wert auch ein oder mehrere '=' enthält.

Die Antwort besteht semantisch aus mehreren Blöcken. Das hat nichts mit `requests` zu tun, sondern mit der API die da angesprochen wird.

@peko: Das '===' ist tatsächlich auch ein '---', das hat Sirius3 wahrscheinlich einfach nur falsch erinnert. Die API kann mit mehr als einem Datensatz antworten und die einzelnen Datensätze sind durch '---'-Zeilen getrennt. Wobei vor dem ersten Datensatz auch noch eine Information kommt ob ein Fehler aufgetreten ist oder nicht. Das steht aber auch alles auf der Webseite: http://www.opengtindb.org/api.php

Re: String aus einem request.get extrahieren

Verfasst: Montag 1. Juli 2019, 18:36
von peko
Erstmal Danke an alle!
Ich werde den Vorschlag von Sirius3 versuchen umzusetzen.
@ __blackjack__ danke, das habe ich auch gelesen.

Re: String aus einem request.get extrahieren

Verfasst: Montag 1. Juli 2019, 19:15
von peko
Sodele,

der Hinweis von snafu hat das Ergebnis gebracht, das ich suchte.
@__blackjack__ mir reicht der erste Treffer und Produkte mit '=' im Namen gibts hoffentlich nicht so viele

Code: Alles auswählen

#!/usr/bin/python3

import requests
req = requests.get("https://opengtindb.org/?ean=4000540000405&cmd=query&queryid=400000000")
erg = dict(line.split('=') for line in req.text.splitlines() if '=' in line)
print(erg['detailname'])
Extrahiert mir exakt: Kölln Instant Flocken, 1er Pack (1x 250gr)
Das ganze db Geraffel, Ein- und Ausgaben schaffe ich dann wieder alleine.

DANKE an alle für die schnelle Hilfe

Re: String aus einem request.get extrahieren

Verfasst: Montag 1. Juli 2019, 19:26
von __blackjack__
@peko: Damit bekommst Du bei mehreren Datensätzen aber nicht den ersten sondern den letzten. Je nach dem wie vollständig die einzelnen Datensätze sind, kann es auch sein das nicht alle Schlüssel/Wert-Paare tatsächlich zum letzten Datensatz gehören, sondern man am Ende eine Mischung aus mehreren Datensätzen hat.

Und es gibt auch hier das Problem das im Wert keine '=' vorkommen dürfen, weil das sonst mit einer Ausnahme abbricht.

Du solltest auch den Fehlerwert auswerten, bevor Du irgendwelche anderen Zugriffe auf die Daten machst.

Falsche Abkürzungen sind auch immer noch eine schlechte Idee. Man kürzt `response` nicht mit `req` ab, das macht keinen Sinn und verwirrt den Leser.

Edit: Und `erg` soll wohl `ergebnis` heissen.

Re: String aus einem request.get extrahieren

Verfasst: Montag 1. Juli 2019, 19:43
von Sirius3
@peko: da der Wink mit dem Zaunpfahl nicht zu fruchten scheint: die Rückgabe von ›requests.get‹ ist kein Request sondern eine Response!
`erg` hat dann wohl auch nichts mit Ergonomie zu tun, sondern ist ein `ergebnis` oder um nicht Englisch mit Deutsch zu mischen, `result`; und dank mehr als drei Buchstaben gibt es keine Kollision mit response.

Ein einfaches ›, 1‹ würde eines der vielen Probleme beheben, die man sich mit so einer stümperhaften Lösung einfängt. Wo ist das Problem von ein bißchen Sorgfalt?

Re: String aus einem request.get extrahieren

Verfasst: Montag 1. Juli 2019, 20:37
von peko
@sirius - momentan könntest du mich mit dem Zaunpfahl erschlagen, ich komm nicht drauf.
Ich entschuldige mich für den stümperhaften Lösungsansatz und die Frage,
und bedanke mich für die Antworten.
Wo ist das Problem von ein bißchen Höflichkeit ?

Re: String aus einem request.get extrahieren

Verfasst: Montag 1. Juli 2019, 21:41
von snafu
Wie bereits angedeutet wurde, lässt sich das theoretische Problem, dass man ein Gleichheitszeichen im Wert haben könnte, auch lösen. Man muss einfach sagen, dass bloß einmal gesplittet werden soll, indem man den betreffenden Teil anpasst:

Code: Alles auswählen

line.split('=', 1)
Inwieweit das mit den Blöcken bei der Rückgabe praxisrelevant ist, kann ich nicht beurteilen. Anstatt ausfallend zu werden, könnte man ja eine konstruktive Lösung dazu liefern... :)
peko hat geschrieben: Montag 1. Juli 2019, 20:37 @sirius - momentan könntest du mich mit dem Zaunpfahl erschlagen, ich komm nicht drauf.
Es geht einfach darum, dass "request" soviel wie Anfrage heißt und "response" heißt Antwort / Rückmeldung. Was du vom get()-Aufruf zurück bekommst, ist halt die Antwort und nicht die Anfrage.

Re: String aus einem request.get extrahieren

Verfasst: Montag 1. Juli 2019, 22:04
von peko
@snafu
Vielen Dank, jetzt ist der Groschen gefallen.

Re: String aus einem request.get extrahieren

Verfasst: Montag 1. Juli 2019, 22:34
von snafu
Und das mit der Benennung ist so ein Zwiespalt: Einerseits ist bei zwei direkt aufeinanderfolgenden Zeilen die Bedeutung einer Abkürzung klar - da könnte man sogar schlichtweg "r" als Bezeichner nehmen. Andererseits wird durch das Ausschreiben von "response" auch dem unbedarften Leser recht klar, was gemeint ist, ohne dass er in die Doku des "requests"-Modul schauen muss, um sicher zu sein. Auch sind gängige Abkürzungen als Bezeichner hilfreich, wenn man sie oft ansprechen muss und ellenlange Zeilen vermeiden will. Das ist so eine Sache, bei der sich wohl immer die Geister scheiden werden. Auch in etablierten Projekten trifft man auf Abkürzungen und die Programme sind dennoch lesbar und wartbar.