requests在爬取网页时候时候中文显示乱码
import requests url = ‘http://www.neihan8.com/wenzi/index_2.html‘ res = requests.get(url)res.encoding #获取res的编码格式res.headers #获取Content-Type内容res.apparent_encoding #获取网页正确的编码格式 html = res.text# 返回的结果是处理过的Unicode类型的数据 print(res)print(res.encoding)#获得网页源码的格式 打印显示 ISO-8859-1
第一个问题是,为什么会有ISO-8859-1这样的字符集编码?
iso-8859是什么? 他又被叫做Latin-1或“西欧语言” . 对于我来说,这属于requests的一个bug,在requests库的github里可以看到不只是中国人提交了这个issue. 但官方的回复说是按照http rfc设计的。
下面通过查看requests源代码,看这问题是如何造成的 !
requests会从服务器返回的响应头的 Content-Type 去获取字符集编码,如果content-type有charset字段那么requests才能正确识别编码,否则就使用默认的 ISO-8859-1. 一般那些不规范的页面往往有这样的问题. 现在一般的Content-Type 是‘text/html‘。所以现在一般读取源码以后都是用‘ html = res.text‘ 格式读取。但是也可用通过html = res.content来获取返回的源码。
第二个问题, 那么如何获取正确的编码?
requests的返回结果对象里有个apparent_encoding函数, apparent_encoding通过调用chardet.detect()来识别文本编码. 但是需要注意的是,这有些消耗计算资源.
至于为毛,可以看看chardet的源码实现.
第三个问题,requests的text() 跟 content() 有什么区别?
requests在获取网络资源后,我们可以通过两种模式查看内容。 一个是res.text,另一个是res.content,那他们之间有什么区别呢?
分析requests的源代码发现,res.text返回的是处理过的Unicode型的数据,而使用res.content返回的是bytes型的原始数据。也就是说,res.content相对于res.text来说节省了计算资源,res.content是把内容bytes返回. 而res.text是decode成Unicode. 如果headers没有charset字符集的话,text()会调用chardet来计算字符集,这又是消耗cpu的事情.
requests中文乱码解决方法有这么几种
1、由于content是HTTP相应的原始字节串,可以根据headers头部的charset把content decode为unicode,前提别是ISO-8859-1编码.
r.encoding # ‘gbk‘ print r.content.decode(r.encoding)
2、另外有一种特别粗暴方式,就是直接根据chardet的结果来encode成utf-8格式.
r = requests.get(‘http://item.jd.com/1012551875.html‘) r.apparent_encoding # ‘GB2312‘ r.encoding # ‘gbk‘ r.content.decode(r.encoding).encode(‘utf-8‘)# 问题 r.encoding和r.apparent_encoding什么区别????
如果在确定使用text,并已经得知该站的字符集编码时,可以使用 r.encoding = ‘xxx’ 模式, 当你指定编码后,requests在text时会根据你设定的字符集编码进行转换.
>>> import requests >>> r = requests.get(‘https://up.xiaorui.cc‘) >>> r.text >>> r.encoding ‘gbk‘ >>> r.encoding = ‘utf-8‘