python的requests类抓取中文页面出现乱码

requests 是一个python的http请求类库,基于urllib3,但支持更多的特性以及更人性化的API。

最近用requests抓取一个中文gb2312编码的页面时,整个页面的中文都乱码了。

基本上乱码就肯定是编码了,首先想到了是不是requests识别编码的时候识别错了,转到其它编码去了。

于是加上调试,打印出来 response.encoding,发现居然是:ISO-8859-1 这个奇怪的编码。

搜索了一下相关的说明,发现 requests 只会简单地从服务器返回的响应头的 Content-Type 去获取编码,如果有 Charset 才能正确识别编码,否则就使用默认的 ISO-8859-1,这样一来某些不规范的服务器返回就必然乱码了。

requests 内部的 utils 提供了一个从返回 body 获取页面编码的函数,get_encodings_from_content,这样如果服务器返回的头不含 Charset,再通过 get_encodings_from_content 就可以知道页面的正确编码了。

知道了原因,解决就容易了,一个方法是写一个 patch 将 requests.models.Response.content 打上补丁,而这明显比较麻烦。

而另一个办法就是先用 ISO-8859-1 再 encode 一次,再用获取的准确的 charset 去decode,这样省事了,不过肯定影响效率并且可能会有转换丢失。

代码:response.text.encode('ISO-8859-1').decode(requests.utils.get_encodings_from_content(response.text)[0]) 。

2014年08月06日