2018年の更新:
2018年2月の時点で、などの圧縮の使用gzip
が非常に一般的になっています(Google、YouTube、Yahoo、Wikipedia、Reddit、Stack Overflow、Stack Exchange Networkサイトなどの大規模なサイトを含む、すべてのWebサイトの約73%が圧縮を使用しています)。
元の回答のようにgzip圧縮された応答で単純なデコードを行うと、次のようなエラーが表示されます。
UnicodeDecodeError: 'utf8'コーデックは位置1のバイト0x8bをデコードできません:予期しないコードバイト
gzpippedレスポンスをデコードするには、次のモジュールを追加する必要があります(Python 3の場合):
import gzip
import io
注: Python 2 StringIO
では、代わりにio
次に、次のようにコンテンツを解析できます。
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
このコードは応答を読み取り、バイトをバッファーに入れます。次に、gzip
モジュールはGZipFile
関数を使用してバッファを読み取ります。その後、gzip圧縮されたファイルを再度バイトに読み込み、最後に通常読み取り可能なテキストにデコードできます。
2010年の元の回答:
使用される実際の値を取得できますlink
か?
さらに.encode()
、すでにエンコードされたバイト文字列を使おうとすると、通常この問題が発生します。だからあなたは最初にそれをデコードしようとするかもしれません
html = urllib.urlopen(link).read()
unicode_str = html.decode(<source encoding>)
encoded_str = unicode_str.encode("utf8")
例として:
html = '\xa0'
encoded_str = html.encode("utf8")
失敗する
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 0: ordinal not in range(128)
その間:
html = '\xa0'
decoded_str = html.decode("windows-1252")
encoded_str = decoded_str.encode("utf8")
エラーなしで成功します。「windows-1252」は例として使用したものであることに注意してください。私はシャルデからこれを手に入れました、そしてそれはそれが正しいという0.5の自信を持っていました!(まあ、1文字の長さの文字列で与えられたように、あなたは何を期待していますか)それを、返されたバイト文字列のエンコーディングに、.urlopen().read()
取得したコンテンツに適用されるものに変更する必要があります。
もう1つの問題は、.encode()
stringメソッドが変更された文字列を返し、ソースを適切に変更しないことです。したがってself.response.out.write(html)
、htmlはhtml.encodeからのエンコードされた文字列ではないので、ある意味では意味がありません(それが最初に目的としていた場合)。
Ignacioが示唆したように、から返された文字列の実際のエンコーディングについては、ソースWebページを確認してくださいread()
。メタタグの1つ、または応答のContentTypeヘッダーにあります。それをのパラメーターとして使用します.decode()
。
ただし、ヘッダーやメタ文字セットの宣言が実際のコンテンツと一致することを確認する責任は他の開発者にあるとは限りません。(これはPITAです。ええ、知っておくべきですが、私は以前の1人でした)。