2018年更新:
截至2018年2月,使用像gzip
这样的压缩方式已经变得相当流行(约73%的网站使用它,包括Google、YouTube、Yahoo、Wikipedia、Reddit、Stack Overflow和Stack Exchange Network等大型网站)。
如果你对一个已经被gzipped的响应进行简单的解码,你会得到一个类似于以下的错误信息:
UnicodeDecodeError: 'utf8' codec can't decode byte 0x8b in position 1: unexpected code byte
为了解码一个被gzip压缩过的响应,在Python 3中,你需要添加以下模块:
import gzip
import io
注意: 在Python 2中,您需要使用StringIO
而不是io
然后您可以像这样解析内容:
response = urlopen("https://example.com/gzipped-ressource")
buffer = io.BytesIO(response.read())
gzipped_file = gzip.GzipFile(fileobj=buffer)
decoded = gzipped_file.read()
content = decoded.decode("utf-8")
此代码读取响应,并将字节放入缓冲区。然后,gzip
模块使用GZipFile
函数读取缓冲区中的内容。然后,压缩文件可以再次读入字节并在最终解码为可读文本。
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”只是我用作示例的内容。我从
chardet获取了这个值,并且它有0.5的置信度是正确的!(好吧,因为给出的是一个1个字符长度的字符串,你期望什么呢)您应该将其更改为从
.urlopen().read()
返回的字节字符串的编码适用于您检索到的内容。
我看到的另一个问题是.encode()
字符串方法返回修改后的字符串,而不是在原地修改源。因此,将self.response.out.write(html)
作为html无法成为来自html.encode的编码字符串(如果这是您最初的目标)。
正如Ignacio建议的那样,请检查源网页以获取从read()
返回的实际编码方式。它可以在Meta标签中或响应的ContentType头中。然后将其用作.decode()
的参数。
但请注意,不应假定其他开发人员足够负责,以确保标题和/或元字符集声明与实际内容匹配。(这很麻烦,是的,我应该知道,我以前就是其中之一)。
c2
字节,否则可能会出现解码错误:http://hexutf8.com/?q=C2A0 - jar\x1b[38;5;226m...
的文本的人,这是ansi转义码,而不是Unicode。 - SurpriseDog