2018 Güncellemesi:
Şubat 2018 itibariyle, gibi sıkıştırmalar kullanmak oldukça popülergzip
hale geldi (Google, YouTube, Yahoo, Wikipedia, Reddit, Stack Overflow ve Stack Exchange Network siteleri gibi büyük siteler dahil olmak üzere tüm web sitelerinin yaklaşık% 73'ü bunu kullanıyor).
Orijinal cevaptaki gibi basit bir kod çözme işlemi yaparsanız, buna benzer bir hata alırsınız:
UnicodeDecodeError: 'utf8' codec bileşeni, konum 1'deki bayt 0x8b kodunu çözemiyor: beklenmeyen kod baytı
Bir gzpipped yanıtının kodunu çözmek için aşağıdaki modülleri eklemeniz gerekir (Python 3'te):
import gzip
import io
Not: Python 2'de kullanmak StringIO
yerineio
Ardından içeriği şu şekilde ayrıştırabilirsiniz:
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
Bu kod yanıtı okur ve baytları arabelleğe yerleştirir. gzip
Ardından modül kullanarak tampon okur GZipFile
işlevi. Bundan sonra, gzip edilmiş dosya tekrar baytlara okunabilir ve sonunda normal olarak okunabilir metne çözülebilir.
2010'dan Orijinal Yanıt:
Kullanılan gerçek değeri alabilir miyiz link
?
Ayrıca, .encode()
zaten kodlanmış bir bayt dizesini denemeye çalışırken genellikle bu sorunla karşılaşırız . Yani önce olduğu gibi kodunu çözmeyi deneyebilirsiniz
html = urllib.urlopen(link).read()
unicode_str = html.decode(<source encoding>)
encoded_str = unicode_str.encode("utf8")
Örnek olarak:
html = '\xa0'
encoded_str = html.encode("utf8")
İle başarısız olur
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 0: ordinal not in range(128)
Süre:
html = '\xa0'
decoded_str = html.decode("windows-1252")
encoded_str = decoded_str.encode("utf8")
Hatasız başarılı olur. "Windows-1252" nin örnek olarak kullandığım bir şey olduğunu unutmayın . Bunu pazıdan aldım ve doğru olduğuna dair 0,5 güven vardı! (iyi, 1 karakter uzunluğunda bir dize ile verildiği gibi, ne bekliyorsunuz) Bunu, aldığınız .urlopen().read()
içerik için geçerli olana döndürülen bayt dizesinin kodlamasına değiştirmelisiniz .
Başka bir sorun var .encode()
dize yöntemi değiştirilmiş dize döndürür ve yerinde kaynak değiştirmez olduğunu görüyorum . Bu yüzden self.response.out.write(html)
html, html.encode'dan kodlanmış dize olmadığı için işe yaramaz (eğer başlangıçta amaçladığınız buysa).
Ignacio'nun önerdiği gibi, döndürülen dizenin gerçek kodlaması için kaynak web sayfasını kontrol edin read()
. Yanıtta Meta etiketlerinden birinde veya ContentType üstbilgisinde bulunur. Bunu parametre olarak kullanın .decode()
.
Ancak, diğer geliştiricilerin üstbilgi ve / veya meta karakter kümesi bildirimlerinin gerçek içerikle eşleştiğinden emin olmak için yeterince sorumlu olduğu varsayılmamalıdır. (Bu bir PITA, evet, bilmeliyim, daha önce onlardan biriydim).