2018年更新:
截至2018年2月,使用类似的压缩gzip
已变得非常流行(大约73%的网站都在使用它,包括Google,YouTube,Yahoo,Wikipedia,Reddit,Stack Overflow和Stack Exchange Network网站等大型网站)。
如果您像原始答案中那样使用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
函数读取缓冲区。之后,可以将压缩后的文件再次读取为字节,最后将其解码为正常可读的文本。
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不是html.encode中的编码字符串(如果这是您最初的目标)。
正如Ignacio所建议的那样,请在源网页上检查从中返回的字符串的实际编码read()
。它位于响应的Meta标签之一或ContentType标头中。然后将其用作的参数.decode()
。
但是请注意,不应假定其他开发人员负责确保标题和/或元字符集声明与实际内容匹配。(这是PITA,是的,我应该知道,我以前是其中的一个)。