Pembaruan 2018:
Pada Februari 2018, menggunakan kompresi seperti gzip
telah menjadi sangat populer (sekitar 73% dari semua situs web menggunakannya, termasuk situs besar seperti Google, YouTube, Yahoo, Wikipedia, Reddit, Stack Overflow, dan Stack Exchange Network).
Jika Anda melakukan decode sederhana seperti pada jawaban asli dengan respons yang di-gzip, Anda akan mendapatkan kesalahan seperti atau mirip dengan ini:
UnicodeDecodeError: codec 'utf8' tidak dapat mendekode byte 0x8b di posisi 1: byte kode yang tidak terduga
Untuk men-decode respons gzpipped, Anda perlu menambahkan modul berikut (dengan Python 3):
import gzip
import io
Catatan: Dalam Python 2 Anda akan menggunakan StringIO
sebagai gantinyaio
Kemudian Anda dapat menguraikan konten seperti ini:
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
Kode ini membaca respons, dan menempatkan byte dalam buffer. The gzip
modul kemudian membaca buffer menggunakan GZipFile
fungsi. Setelah itu, file yang di-gzip dapat dibaca menjadi byte lagi dan diterjemahkan ke teks yang biasanya dapat dibaca pada akhirnya.
Jawaban Asli dari 2010:
Bisakah kita mendapatkan nilai aktual yang digunakan link
?
Selain itu, kami biasanya menghadapi masalah ini di sini ketika kami mencoba untuk .encode()
byte string yang sudah dikodekan. Jadi, Anda dapat mencoba memecahkan kode itu terlebih dahulu seperti pada
html = urllib.urlopen(link).read()
unicode_str = html.decode(<source encoding>)
encoded_str = unicode_str.encode("utf8")
Sebagai contoh:
html = '\xa0'
encoded_str = html.encode("utf8")
Gagal dengan
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 0: ordinal not in range(128)
Sementara:
html = '\xa0'
decoded_str = html.decode("windows-1252")
encoded_str = decoded_str.encode("utf8")
Berhasil tanpa kesalahan. Perhatikan bahwa "windows-1252" adalah sesuatu yang saya gunakan sebagai contoh . Saya mendapat ini dari chardet dan memiliki 0,5 keyakinan bahwa itu benar! (well, seperti yang diberikan dengan string 1-karakter-panjang, apa yang Anda harapkan) Anda harus mengubahnya ke pengkodean string byte yang dikembalikan dari .urlopen().read()
ke apa yang berlaku untuk konten yang Anda ambil.
Masalah lain yang saya lihat di sana adalah bahwa .encode()
metode string mengembalikan string yang dimodifikasi dan tidak mengubah sumber di tempatnya. Jadi agak tidak berguna untuk memiliki self.response.out.write(html)
html bukan string yang disandikan dari html.encode (jika itu yang awalnya Anda tuju).
Seperti yang disarankan Ignacio, periksa halaman web sumber untuk pengkodean sebenarnya dari string yang dikembalikan read()
. Entah itu di salah satu tag Meta atau di header ContentType dalam respons. Gunakan itu sebagai parameter untuk .decode()
.
Namun perlu dicatat bahwa tidak boleh diasumsikan bahwa pengembang lain cukup bertanggung jawab untuk memastikan deklarasi header dan / atau karakter meta cocok dengan konten yang sebenarnya. (Yang merupakan PITA, ya, saya harus tahu, saya adalah salah satu dari mereka sebelumnya).