Python reqeusts在作为代理爬虫节点抓取不同字符集网站时遇到的一些问题总结. 简单说就是中文乱码的问题.   如果单纯的抓取微博,微信,电商,那么字符集charset很容易就确认,你甚至可以单方面把encoding给固定住。 但作为舆情数据来说,他每天要抓取几十万个不同网站的敏感数据,所以这就需要我们更好确认字符集编码,避免中文的乱码情况. 


该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新。

http://xiaorui.cc/2016/02/19/%E4%BB%A3%E7%A0%81%E5%88%86%E6%9E%90python-requests%E5%BA%93%E4%B8%AD%E6%96%87%E7%BC%96%E7%A0%81%E9%97%AE%E9%A2%98/

我们首先看这个例子. 你会发现一些有意思的事情. 

第一个问题是,为什么会有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. 一般那些不规范的页面往往有这样的问题. 

文件: requests.utils.py

第二个问题, 那么如何获取正确的编码? 

requests的返回结果对象里有个apparent_encoding函数, apparent_encoding通过调用chardet.detect()来识别文本编码. 但是需要注意的是,这有些消耗计算资源.
至于为毛,可以看看chardet的源码实现. 

第三个问题,requests的text() 跟 content() 有什么区别? 

requests在获取网络资源后,我们可以通过两种模式查看内容。 一个是r.text,另一个是r.content,那他们之间有什么区别呢?

分析requests的源代码发现,r.text返回的是处理过的Unicode型的数据,而使用r.content返回的是bytes型的原始数据。也就是说,r.content相对于r.text来说节省了计算资源,r.content是把内容bytes返回. 而r.text是decode成Unicode. 如果headers没有charset字符集的化,text()会调用chardet来计算字符集,这又是消耗cpu的事情.

通过看requests代码来分析text() content()的区别.

对于requests中文乱码解决方法有这么几种. 

方法一: 

由于content是HTTP相应的原始字节串,可以根据headers头部的charset把content decode为unicode,前提别是ISO-8859-1编码.


另外有一种特别粗暴方式,就是直接根据chardet的结果来encode成utf-8格式. 

如果在确定使用text,并已经得知该站的字符集编码时,可以使用 r.encoding = ‘xxx’ 模式, 当你指定编码后,requests在text时会根据你设定的字符集编码进行转换. 

方法二:

根据我抓几十万的网站的经验,大多数网站还是很规范的,如果headers头部没有charset,那么就从html的meta中抽取.

python requests的utils.py里已经有个完善的从html中获取meta charset的函数. 说白了还是一对的正则表达式.


文件: utils.py

最后,针对requests中文乱码的问题总结:

统一编码,要不都成utf-8, 要不就用unicode做中间码 ! 

国内的站点一般是utf-8、gbk、gb2312  , 当requests的encoding是这些字符集编码后,是可以直接decode成unicode. 

但当你判断出encoding是 ISO-8859-1 时,可以结合re正则和chardet判断出他的真实编码. 可以把这逻辑封装补丁引入进来.

Python3.x解决了这编码问题,如果你还是python2.6 2.7,那么还需要用上面的方法解决中文乱码的问题. 

END.



对Python及运维开发感兴趣的朋友可以加QQ群 : 478476595 !!!

另外如果大家觉得文章对你有些作用!   帮忙点击广告. 一来能刺激我写博客的欲望,二来好维护云主机的费用.
如果想赏钱,可以用微信扫描下面的二维码. 另外再次标注博客原地址  xiaorui.cc  ……   感谢!

解决requests的logging日志提示问题

解决requests的logging日志提示问题 python下哪个httpclient最好用,我想大家首选都是requets 。 这次使用requests调用nlp,分词http服务的时候,会提示大量...

阅读全文

分析requests源码解决headers无法json问题

今又在丰富mock http接口了,由于我的开发速度太快,同事们的开发速度太慢,哈哈别打我, 他们在一定程度上拖慢了哥的大腿.  但又因为哥的接口要大量...

阅读全文

多进程下用requests访问http api时遇到的坑

简单描述下场景,我这边开发了一个服务是用来把Mysql的数据取出来,并进行分词及正负面操作后再导出到elasticsearch里面。  其实是多线程开发的,原本以...

阅读全文

  1. 对,这个问题我原来也读过源码找过这个bug,这种处理方式就是安装HTTP规范来做的。参考我写的博客:http://www.cnblogs.com/bitpeng/p/4748872.html