Python requests中的编码问题

你可以用.decode('gdk', errors='ignore')或者.decode('gdk', errors='replace')来解码

来自xiaorui.cc

Python

reqeusts抓取返回页面时,碰到页面乱码

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

#blog: xiaorui.cc

@property

def apparent_encoding(self):

"""使用chardet来计算编码"""

return chardet.detect(self.content)['encoding']

第三个问题,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编码.

In [96]: r.encoding

Out[96]: 'gbk'

In [98]: print r.content.decode(r.encoding)[200:300]

="keywords" content="Python数据分析与挖掘实战,,机械工业出版社,9787111521235,,在线购买,折扣,打折"/>

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

#http://xiaorui.ccIn [22]: r  = requests.get('http://item.jd.com/1012551875.html')In [23]: print r.contentKeyboardInterruptIn [23]: r.apparent_encodingOut[23]: 'GB2312'In [24]: r.encodingOut[24]: 'gbk'In [25]: r.content.decode(r.encoding).encode('utf-8')---------------------------------------------------------------------------UnicodeDecodeError                        Traceback (most recent call last)in()

----> 1 r.content.decode(r.apparent_encoding).encode('utf-8')

UnicodeDecodeError: 'gb2312' codec can't decode bytes in position 49882-49883: illegal multibyte sequence

In [27]: r.content.decode(r.apparent_encoding,'replace').encode('utf-8')

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

>>>import requests

>>>r=requests.get('https://up.xiaorui.cc')

>>>r.text

>>>r.encoding

'gbk'

>>>r.encoding='utf-8'

方法二:

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

In [78]: s

Out[78]: '    [^;\s]+)", flags=re.I)

In [80]: b.search(s).group(1)

Out[80]: 'gbk"'



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

In [32]: requests.utils.get_encodings_from_content(r.content)

Out[32]: ['gbk']

文件: utils.py

def get_encodings_from_content(content):

charset_re = re.compile(r']', flags=re.I)

pragma_re = re.compile(r']', flags=re.I)

xml_re = re.compile(r'^<\?xml.*?encoding=["\']*(.+?)["\'>]')

return (charset_re.findall(content) +

pragma_re.findall(content) +

xml_re.findall(content))

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

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

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

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

import requests

def monkey_patch():

prop = requests.models.Response.content

def content(self):

_content = prop.fget(self)

if self.encoding == 'ISO-8859-1':

encodings = requests.utils.get_encodings_from_content(_content)

if encodings:

self.encoding = encodings[0]

else:

self.encoding = self.apparent_encoding

_content = _content.decode(self.encoding, 'replace').encode('utf8', 'replace')

self._content = _content

return _content

requests.models.Response.content = property(content)

monkey_patch()

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

END.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容