Update 2018:
Ab Februar 2018 mit Kompressionen wie gzip
hat sich zu sehr beliebt (rund 73% aller Websites nutzen es, darunter große Websites wie Google, YouTube, Yahoo, Wikipedia, Reddit, Stack - Überlauf und Stapel Exchange Network Sites).
Wenn Sie eine einfache Dekodierung wie in der ursprünglichen Antwort mit einer gezippten Antwort durchführen, wird ein Fehler wie der folgende angezeigt:
UnicodeDecodeError: Der Codec 'utf8' kann das Byte 0x8b an Position 1 nicht dekodieren: Unerwartetes Codebyte
Um eine gzpipped-Antwort zu dekodieren, müssen Sie die folgenden Module hinzufügen (in Python 3):
import gzip
import io
Hinweis: In Python 2 würden Sie StringIO
anstelle von verwendenio
Dann können Sie den Inhalt folgendermaßen analysieren:
response = urlopen("https://example.com/gzipped-ressource")
buffer = io.BytesIO(response.read()) # Use StringIO.StringIO(response.read()) in Python 2
gzipped_file = gzip.GzipFile(fileobj=buffer)
decoded = gzipped_file.read()
content = decoded.decode("utf-8") # Replace utf-8 with the source encoding of your requested resource
Dieser Code liest die Antwort und legt die Bytes in einem Puffer ab. Das gzip
Modul liest dann den Puffer mit der GZipFile
Funktion. Danach kann die komprimierte Datei wieder in Bytes eingelesen und am Ende in normal lesbaren Text dekodiert werden.
Ursprüngliche Antwort von 2010:
Können wir den tatsächlichen Wert erhalten, für den verwendet wird? link
?
Außerdem tritt dieses Problem normalerweise hier auf, wenn wir versuchen, .encode()
eine bereits codierte Bytezeichenfolge zu verwenden. Sie könnten also versuchen, es zuerst wie in zu dekodieren
html = urllib.urlopen(link).read()
unicode_str = html.decode(<source encoding>)
encoded_str = unicode_str.encode("utf8")
Als Beispiel:
html = '\xa0'
encoded_str = html.encode("utf8")
Schlägt mit
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 0: ordinal not in range(128)
Während:
html = '\xa0'
decoded_str = html.decode("windows-1252")
encoded_str = decoded_str.encode("utf8")
Gelingt ohne Fehler. Beachten Sie, dass "Windows-1252" etwas ist, das ich als Beispiel verwendet habe . Ich habe das von Chardet bekommen und es hatte 0,5 Vertrauen, dass es richtig ist! (Nun, wie bei einer Zeichenfolge mit einer Länge von 1 Zeichen angegeben, was erwarten Sie?) Sie sollten dies in die Codierung der zurückgegebenen Byte-Zeichenfolge ändern.urlopen().read()
Ihnen abgerufenen Inhalt gilt.
Ein weiteres Problem, das ich dort sehe, ist, dass die .encode()
Zeichenfolgenmethode die geänderte Zeichenfolge zurückgibt und die Quelle nicht an Ort und Stelle ändert. Es ist also nutzlos, self.response.out.write(html)
wenn HTML nicht die codierte Zeichenfolge aus html.encode ist (wenn Sie dies ursprünglich angestrebt haben).
Überprüfen Sie, wie von Ignacio vorgeschlagen, die Quellwebseite auf die tatsächliche Codierung der zurückgegebenen Zeichenfolge von read()
. Es befindet sich entweder in einem der Meta-Tags oder im ContentType-Header in der Antwort. Verwenden Sie das dann als Parameter für .decode()
.
Beachten Sie jedoch, dass nicht davon ausgegangen werden sollte, dass andere Entwickler verantwortlich genug sind, um sicherzustellen, dass die Deklarationen für Header und / oder Metazeichensätze mit dem tatsächlichen Inhalt übereinstimmen. (Was eine PITA ist, ja, ich sollte wissen, ich war einer von denen vorher).