Python Requests编码问题解决方案

49 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

C语言学习:size_t

在学习C语言的时候,遇到了一个新的数据类型size_t,截止目前也没有完全理清这个类似的具体场景及出现的原因。
44 sec read

C语言学习:main()函数的正确写法

C语言虽然是一门古老的语言,但是其标准一直在完善,所以很多以前支持的语法在到当前已经不能在使用了。 C语言的版
41 sec read

Scipy数学函数的Scala实现

最近在推进项目的时候,遇到需要将线下的Python代码转化成线上的集群代码,由于机器代码环境是Scala,所以
4 min read

发表评论

电子邮件地址不会被公开。 必填项已用*标注