Python Requests编码问题解决方案

51 sec read

在使用python requests时,有时会出现编码错误的问题,导致的主要原因是编码识别出错了。当获取到的内容出现乱码时,最常出现的错误是将编码识别成了ISO-8859-1。

ISO-8859-1是什么?

ISO 8859-1,正式编号为ISO/IEC 8859-1:1998,又称Latin-1或“西欧语言”,是国际标准化组织内ISO/IEC 8859的第一个8位字符集。它以ASCII为基础,在空置的0xA0-0xFF的范围内,加入96个字母及符号,藉以供使用附加符号的拉丁字母语言使用。

为什么会被识别成ISO-8859-1?

通过出错的页面,我们发现在HTML中已经指明了页面具体的编码还是会出错。

具体原因是?通过查看源码,可以发现默认的编码识别比较简单,直接从响应头文件的Content-Type里获取,如果存在charset,则可以正确识别,如果不存在charset但是存在text就认为是ISO-8859-1,见Lib\site-packages\requests\utils.py。

可以看到,requests会先去找HTTP头部的“Content-Type”字段,如果没有,就调用“charade”来猜测编码。而默认的编码格式正是“ISO-8859-1”。代码中并没有去获取HTML页面中指定的编码格式,关于这样的处理,很多人也在官方的issues中提交了吐槽,但是作者回复是严格http协议标准写这个库的,HTTP协议 RFC 2616中提到,如果HTTP响应中Content-Type字段没有指定charset,则默认页面是’ISO-8859-1’编码。

When you receive a response, Requests makes a guess at the encoding to use for decoding the response when you call the Response.text method. Requests will first check for an encoding in the HTTP header, and if none is present, will use charade to attempt to guess the encoding.

The only time Requests will not do this is if no explicit charset is present in the HTTP headers and the Content-Type header contains text. In this situation, RFC 2616 specifies that the default charset must be ISO-8859-1. Requests follows the specification in this case. If you require a different encoding, you can manually set the Response.encoding property, or use the raw Response.content.

乱码解决方案

如果你知道明确的编码,解决方案非常简单,只需指定具体的编码即可。

当不清楚具体编码的情况下,如何获取准确的页面编码?

其实Requests提供了从内容获取编码,只是在默认中没有使用,见Lib\site-packages\requests\utils.py:

另外还提供了使用chardet的编码检测,见models.py:

针对这三种方式,识别编码的速率及需要的资源不同。

执行结果

最终解决方案,Python2,创建一个requests_patch.py文件,并在代码使用前import它,问题即可解决:

上述代码在Python3 下执行会报如下错误:TypeError: cannot use a string pattern on a bytes-like object,主要原因是python3中.content返回的非字符串数据。想在Python下获取正确的编码,具体代码如下:

打赏作者
微信支付标点符 wechat qrcode
支付宝标点符 alipay qrcode

用户模型之三户模型

10 sec read

常用算法之分治法

分治法概念 分治法(divide-and-conquer)字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。分治有两个特点: 子问题相互独立且与原问题形式 ...
1 min read

使用Python更换外网IP

在进行数据抓取时,经常会遇到IP被限制的情况,常见的解决方案是搭建代理IP池,或购买IP代理的服务。除此之外,还有一个另外的方法就是使用家里的宽带网络进行抓取。由于家里的宽带每次断开重新连接时都会分配一个新的IP,所以在我们抓取数据的时候,判断 ...
36 sec read

Leave a Reply

Your email address will not be published. Required fields are marked *