这个问题一般出现在抓取网页对网页进行解码的时候,比如:

import urllib.request

r = urllib.request.Request('http://www.sina.com')
r.add_header('Accept-encoding', 'gzip')
s = urllib.request.urlopen(r)
con = s.read()
dec = con.decode('gbk')
print(dec)

就会出现:

UnicodeDecodeError: 'gbk' codec can't decode byte 0x8b in position 1: illegal multibyte sequence

原因在于自定义header中,'Accept-encoding'值中包含'gzip',即服务器可以以gzip压缩格式返回请求的页面;gzip压缩的标志是接收到的包的最前面两个字节是:0x1f, 0x8b,这样直接gbk解码一定会出现错误。

解决的方法有两种:

  • header'Accept-encoding'中删去'gzip',这样返回的页面不是压缩格式可以直接解码。不过付出的代价就是数据包的大小会迅速增加,基本上是压缩后的5倍。
  • 对接受到的数据包首先进行gzip解压缩,然后再进行解码。实际上Python内置了gzip压缩解压缩模块,不过我还没试过...