Python requests 编码问题

一些说明

  • 为什么我要写这篇文章?
     
      接着上一篇文章《Python 安装 pyecharts 和 WordCloud 报错解决》中所说,我跟着教程去爬取了网易云音乐某首歌的热评,出现了中文字符乱码的问题,而教程则没有这个问题。折腾了很久 encode 和 decode 之后仍未解决,最后想了想会不会是我自己的问题,而不是数据原始编码的问题?比对了我和作者的代码之后,我发现是爬虫课的嵩天老师给的通用爬虫框架惹的祸,且听我细细道来。

怎么回事

  • 我的代码(关键部分)
try:
    r = requests.post(url, headers=headers, data=user_data)
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    print(r.encoding) # Windows-1256
except:
    traceback.print_exc()

  这里我套用了爬虫课学到了的 try - raise_for_status - except 异常处理,这个没有问题,关键在于 这一行:r.encoding = r.apparent_encoding,它的作用是把修改响应头的编码为 request 分析后认为可能性最大的编码,这里它认为编码是 Windows-1256。我尝试之后发现,如果不修改 r.encoding,那么它的值是 UTF-8,也就是说网易云音乐服务器返回给我们的请求头里的编码是真正的编码,而 requests 却判断错误了,导致程序没有用正确的编码来处理中文字符。
  问题又来了,为什么 r.apparent_encoding 会判断错误呢?首先还是得先说明一下为什么会在已经有 r.encoding 的情况下还要提供 r.apparent_encodinig 这个属性。
  一般来说,如果 requests 得到的响应头没有指定编码或者响应头的编码不能被正常提取出来,requests 这个库会默认把 r.encoding 设置为 ISO-8859-1 (别名:latin-1) 。事实上响应的内容多数情况下不会是 ISO-8859-1,这就导致了响应 body 里的中文不能被正常解析。于是,requests 为它的响应对象增加了一个 apparent_encoding 属性,这个属性实际上是通过另一个 Python 编码检测模块 chardet 来实现的,这个结果仅仅是一种较高可能性,仍然可能会出错。

  • 如何解决

我的想法是,以后爬取得到响应的时候,先判断一下 r.encoding 是否为 ISO-8859-1,如果是的话就说明响应的编码方式没有被正确获取到,这时候在运用 r.encoding = r.apparent_encoding 尝试修正。

(如果 r.apparent_encodiing 猜出来的编码仍是错误的话…….)


写完文章的两个小时后发现: r.encoding = r.apparent_encoding 打印 r.encoding 显示的是 utf-8,是正确的,也就是说这个是个概率事件?每一次计算可能会有不同的结果?不管怎么说先测试一下 r.encoding 总是没有错的。

猜你喜欢

转载自blog.csdn.net/randomparty/article/details/80040493