如何解决requests的ISO-8859-1编码的中文乱码?

如何解决python的requests库的“ISO-8859-1编码下的中文乱码问题呢?

喜欢这个问题 | 分享 | 新建回答

回答

jerkzhang

Sep 16, 2019
2 赞

在使用Python的requests库进行爬虫时,经常会出现中文乱码问题,大多情况下,查看r.encoding会显示是“ISO-8859-1”这类编码格式(一般常用的是utf-8格式),因此导致中文乱码。(大多中文乱码都是ISO-8859-1 问题导致的)

不过,虽然r.encoding显示的是“ISO-8859-1”编码格式,但未必服务器返回的html代码就真的是“ISO-8859-1”编码;因为requests库设计的时候是根据HTML标准来设计的,HTML标准中把返回页面的头文件中不对charset进行指定的都默认为“ISO-8859-1”编码。(这就是问题的根源所在,其实未必是ISO-8859-1编码,也许很可能是GB2312编码格式


ISO-8859-1乱码问题解决方案1(简单,但非全部有效):

比较简单直接的方式就是将“r.encoding”设置成“utf-8”即可。很多情况下,这种方式就ok啦;但是不是对所有站点有效,有些古老而不思进取的站点则依然乱码。不过如果是已知的某个站点,遇到“ISO-8859-1”乱码问题,设置“r.encoding=utf-8”有效的话,那就直接使用这种简单的方法即可。

# coding=utf-8
import requests

url = "https://..." # 换成自己的目标网址
r = requests.get( url )
r.encoding = 'utf-8' # 将ISO-8859-1编码格式转换为UTF-8格式
print r.text # 这时输出就没有中文乱码问题啦


ISO-8859-1乱码问题解决方案2(复杂但更加广泛适用):

requests库中的utils模块中其实已经准备了get_encodings_from_content方法,该方法的功能是从返回的内容中获取页面的编码格式;另外查看返回对象的apprent_encoding也可以查看页面的真正的编码格式。综合两种方法,写一个函数来获取返回对象的text属性。如下所示,可更加完美地解决ISO-8859-1中文乱码问题:

# coding=utf-8
import requests

def get_text( r ):
    if r.encoding == 'ISO-8859-1':
        true_encoding = requests.utils.get_encodings_from_content( r.text )
        if true_encoding:
            true_encoding = true_encoding[0]
        else:
            true_encoding = r.apparent_encoding
        # 根据真正的编码格式对内容进行解码
        true_text = r.content.decode(true_encoding, 'replace')
    else:
        true_text = r.text
    return true_text

if __name__ == "__main__":
    url = "https://..." # 换成自己的目标网址
    r = requests.get( url )
    print get_text( r ) # 这时输出就没有中文乱码问题啦

如上所示,使用预设的get_text方法即可获取正确解码转换的结果。