Brotli

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.
Kusja
User
Beiträge: 18
Registriert: Mittwoch 18. Dezember 2019, 20:54

Hallo zusammen. Ich muss für die Hochschule folgende Aufgabe lösen:

'Senden Sie eine GET Request an http://httpbin.org/brotli. Sehen Sie sich die Eigenschaftcontent Ihrer Response an und finden Sie einen Weg, den Inhalt von content in Plain Text zuübersetzen.'

Mein Code sieht wie folgt aus:

Code: Alles auswählen

import requests, brotli

response = requests.get('http://httpbin.org/brotli')

print('Response-----------------------------------')
print(response.content)
print('-------------------------------------------')

data = brotli.decompress(response.content)
print('Meaning: ')
print(data)
Die Konsolo spuckt mir hierbei einen error.:

brotli.error: BrotliDecompress failed

Für eure Hilfe bin ich sehr dankbar :).

Liebe Grüße
Kusja
nezzcarth
User
Beiträge: 1634
Registriert: Samstag 16. April 2011, 12:47

Dein Ansatz ist denke ich falsch. Wenn die brotli Bibliothek installiert ist, kümmert sich requests alleine darum, das zu dekodieren. Von dir wird denke ich etwas anderes verlangt; requests hat dafür eine eingebaute Methode. Schau dir "content" mal genauer an. Das ist ja der Sinn von 'content', dass da bereits die Dekodierung stattgefunden hat.
Benutzeravatar
__blackjack__
User
Beiträge: 13102
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@nezzcarth: Also bei mir kümmert sich `requests` da nicht drum. Bei mir funktioniert dann aber auch was der OP da macht ohne eine Ausnahme.

Code: Alles auswählen

In [209]: response = requests.get('http://httpbin.org/brotli')                  

In [210]: print(brotli.decompress(response.content).decode())                   
{
  "brotli": true, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.24.0", 
    "X-Amzn-Trace-Id": "Root=1-5f0762d2-e96b31fc0c98f90a69c586ae"
  }, 
  "method": "GET", 
  "origin": "79.230.157.192"
}
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
nezzcarth
User
Beiträge: 1634
Registriert: Samstag 16. April 2011, 12:47

__blackjack__ hat geschrieben: Donnerstag 9. Juli 2020, 19:34 @nezzcarth: Also bei mir kümmert sich `requests` da nicht drum.
Vielleicht ist das ein Versionsunterschied?

Code: Alles auswählen

Python 3.8.3 (default, May 17 2020, 18:15:42) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.16.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import requests                                                         

In [2]: response = requests.get('http://httpbin.org/brotli')                    

In [3]: response.content                                                        
Out[3]: b'{\n  "brotli": true, \n  "headers": {\n    "Accept": "*/*", \n    "Accept-Encoding": "gzip, deflate", \n    "Host": "httpbin.org", \n    "User-Agent": "python-requests/xxxx", \n    "X-Amzn-Trace-Id": "Root=xxx\n  }, \n  "method": "GET", \n  "origin": "xxx.xxx.xxx.xxx"\n}\n'

Benutzeravatar
__blackjack__
User
Beiträge: 13102
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

qnezzcarth: Ja, das scheint ein Unterschied bei `urllib3` zu sein. Vorher urllib3-1.22, jetzt urllib3-1.25.9. Bei letzterer geht's dann auch automagisch.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Kusja
User
Beiträge: 18
Registriert: Mittwoch 18. Dezember 2019, 20:54

Ich muss ja den content in einen Plain Text umcordieren. Und laut der Dozenten geht es mit brotli. Nur wie man dort den richtigen Code schreibt ist mir schleierhaft. Im Internet finde ich zwar Beiträge zu diesem Thema aber keine Erklärung wie das geschrieben wird.
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

Wie sieht denn dein Content aus?
Kusja
User
Beiträge: 18
Registriert: Mittwoch 18. Dezember 2019, 20:54

Der content ist vom Typ json.

Code: Alles auswählen

b'{\n  "brotli": true, \n  "headers": {\n    "Accept": "*/*", \n    "Accept-Encoding": "gzip, deflate", \n    "Host": "httpbin.org", \n    "User-Agent": "python-requests/2.24.0", \n    "X-Amzn-Trace-Id": "Root=1-5f082ba9-3c73cc09eaf15846ad6cec54"\n  }, \n  "method": "GET", \n  "origin": "87.123.198.239"\n}\n'
Verstehe nicht ganz was er mit Plain Text meint. Meiner Auffassung würde ich dies einfach in json umcodieren.
Kusja
User
Beiträge: 18
Registriert: Mittwoch 18. Dezember 2019, 20:54

@__blackjack__ ich verstehe nicht warum dein Code den Content in json formatiert und bei mir immer wieder der selbe error kommt.
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

Ich befürchte, da hat die Realität deinen Dozenten überholt.
requests hat den Content bereits dekodiert. Scheint, wie __blackjack__ ja oben gezeigt hat, nicht immer so gewesen zu sein.
Kusja
User
Beiträge: 18
Registriert: Mittwoch 18. Dezember 2019, 20:54

Wenn ich es auf diese Weise mache funktioniert das.

Code: Alles auswählen

import requests

response = requests.get('http://httpbin.org/brotli')                  

print(response.text)
Ausgabe :

Code: Alles auswählen

{
  "brotli": true,
  "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate",
    "Host": "httpbin.org",
    "User-Agent": "python-requests/2.24.0",
    "X-Amzn-Trace-Id": "Root=1-5f082f95-9cb5d254252a4b7e17227442"
  },
  "method": "GET",
  "origin": "87.123.198.239"
}
nezzcarth
User
Beiträge: 1634
Registriert: Samstag 16. April 2011, 12:47

Ausgeben ist kein Dekodieren für mich. Ich würde das JSON noch parsen (lassen). Dafür hat requests, wie bereits gesagt, eine eingebaute Methode.
Benutzeravatar
__blackjack__
User
Beiträge: 13102
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@nezzcarth: Das ist aber nicht die Aufgabe. Die Aufgabe ist „finden Sie einen Weg, den Inhalt von content in Plain Text zuübersetzen.“

Und das ist einfach das `text`-Attribut wenn `requests` beziehungsweise `urllib3` das Entpacken bereits übernimmt.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
nezzcarth
User
Beiträge: 1634
Registriert: Samstag 16. April 2011, 12:47

Dann ist die Aufgabe meiner Meinung nach aber nicht lösbar, denn - das mag jetzt Erbsenzählerei sein - streng genommen ist Json ja nun mal Json und kein Plain Text.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@nezzcarth: Plain Text wird hier als Objekt des Typs str verstanden. response.content sind Bytes und response.text eben Text.
Benutzeravatar
__blackjack__
User
Beiträge: 13102
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@nezzcarth: Es ist doch egal was es letztlich ist, die Aufgabe ist ja `contents`, also Bytes in Text zu ”übersetzen” und *das* geht. Völlig unabhängig davon ob man den Text dann noch als BASIC-Quelltext, CSV, JSON, XML, oder sonst was interpretieren könnte.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Kusja
User
Beiträge: 18
Registriert: Mittwoch 18. Dezember 2019, 20:54

Ich hätte da noch eine Frage. Ich habe eine json Datei (clients.json):

Code: Alles auswählen

[
  {
    "id": "d6317eca-bb8d-47a2-871a-80eea6ca39b3",
    "data": {
      "name": "Fox Richardson",
      "contact": {
        "digital": {
          "email": "foxrichardson@aquasure.com"
        },
        "real": {
          "city": "Ezel",
          "street": "Locust Avenue"
        }
      }
    }
  },
  {
    "id": "2bb7d904-3b76-4cc2-97b6-f2670697482c",
    "data": {
      "name": "Gabrielle Fields",
      "contact": {
        "digital": {
          "email": "gabriellefields@aquasure.com"
        },
        "real": {
          "city": "Barstow",
          "street": "Veterans Avenue"
        }
      }
    }
  },
  {
    "id": "7bef15ff-adfe-4371-af0d-79438a42728b",
    "data": {
      "name": "Hess Sweeney",
      "contact": {
        "digital": {
          "email": "hesssweeney@aquasure.com"
        },
        "real": {
          "city": "Loretto",
          "street": "Gem Street"
        }
      }
    }
  }
]
Und hierbei möchte ich mir den Namen, die Email und den Wohnort ausgeben lassen.

Mein Code:

Code: Alles auswählen

import json
# import os.path
# print(os.path.exists('clients.json'))

f = open('clients.json', 'r')
y = json.load(f)

for row in y:
    print('Mein Name ist', row['data']['name'], 'und ich bin unter der E-Mail: ', 
        row['data']['contact']['digital']['email'], 
        'erreichbar und wohne in', row['real']['city'])
Error: KeyError : 'real'

Wenn ich nur den Namen und die Email auslesen funktioniert es. Sobald ich aber 'real' 'city' einfüge kommt der oben genannte Fehler.

Hat jemand eine Lösung für mich.

Json ist neu für mich und ich weiß nicht genau wie man dort den Wohnort auslist.

Und könnte mir einer den wesentlichen Unterschied zwischen
load & loads und dump & dumps erläutern? Ich komme jedes mal durcheinander.

MfG

Kusja
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Json ist neu für mich und ich weiß nicht genau wie man dort den Wohnort auslist.
Das praktische (für Python-Programmierer) ist, dass sich eine JSON-Struktur sehr gut als Python Datenstruktur abbilden lässt. Ein JSON-Object ist wie ein Python Dict und ein JSON Array wie eine Python Liste.

Im gegebenen Bespiel: du hast eine Liste mit drei Dicts, die wiederum Dicts enthalten.
load & loads und dump & dumps erläutern? Ich komme jedes mal durcheinander.
load und dump erwarten ein "file-like objekt", um daraus zu Lesen bzw. dahin zu schreiben, loads und dumps eine String (oder Bytes oder Bytearray). Eselsbrücke: das "s" bei loads und dumps steht für "String".

Gruß, noisefloor
Kusja
User
Beiträge: 18
Registriert: Mittwoch 18. Dezember 2019, 20:54

Danke erst mal für die schnelle Antwort. Ich sitze gerade ziemlich auf dem Schlauch. Ich greife im Code ja so auf den Wert zu wie auch im dict. Nur leider kommt jedes mal der KeyError... Ich weiß auch nicht was ich dort falsch mache.

ACH, Vielen Dank! Mit dem 'S' ist echt eine gute Eselsbrücke :):
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

das Dict ist auch anders verschachtelt. Im Zweifelsfall hilft immer: Klammer zählen :-)

Code: Alles auswählen

>>> row = {
...     "id": "7bef15ff-adfe-4371-af0d-79438a42728b",
...     "data": {
...       "name": "Hess Sweeney",
...       "contact": {
...         "digital": {
...           "email": "hesssweeney@aquasure.com"
...         },
...         "real": {
...           "city": "Loretto",
...           "street": "Gem Street"
...         }
...       }
...     }
...   }
>>> row
{'id': '7bef15ff-adfe-4371-af0d-79438a42728b', 'data': {'name': 'Hess Sweeney', 'contact': {'digital': {'email': 'hesssweeney@aquasure.com'}, 'real': {'city': 'Loretto', 'street': 'Gem Street'}}}}
>>> row['data']['contact']['real']['city']
'Loretto'
>>> 
Gruß, noisefloor
Antworten