adminlzzs'blog

网络安全爱好者/Python爱好者/不会说话却喜欢看别人辩论的渣渣

Python2的中文编码问题

python编码错误和中文的乱码问题,研究了整整两天,查阅了很多资料,也走了一些弯路,我把经验写下,让新手少走点弯路,本人技术较渣,有什么疏漏错误望大牛指正!

以下str表示文本字符,byte表示字节流。

py3只有str和byte,str只能encode,byte只能decode,不需要显式地通过unicode这个“中间人”…py2就必须会经过unicode这个”中间人”….

主要讲一下py2的编码方式,因为现在用py2来造轮子的人挺多的,很多新手会因为中文乱码的问题很头疼,尤其是抓去网页的数据的时候….

首先必须要知道输入的str会被系统以什么方式去编码,是utf-8还是gbk还是其他的编码方式,用chartdet包可以来判断。chardet包在win下要自行安装!

import chardet

s=’大家好,我叫卓少!’

chardet.detect(s)

{'confidence': 0.99, 'encoding': 'GB2312'}

判断出这个输入将会以GB2312去编码,用print 输出也是GB2312编码的中文。一般这种是在windows下py环境里的,GBK系列的编码方式就是windows下默认的,Linux下的编码方式一般是utf-8,输出也一样(这里讲的都是中文的编码方式,英文的默认是ascii…中文用ascii也编码不了…才128个字符...)

 

上面这种输入情况是自己敲键盘打进去的,还有一种输入情况是你在网页上爬取的str,这种你就要看看这个网站是什么编码方式了,打开网页的源代码,上面可以看到chardet=’xxx’…一般现在基本都用的是utf-8编码(utf-8是unicode中综合性最好的编码方式了,而且是包含了全世界各种语言字符的集合,大而全)。知道了网页的编码之后,我们分别来尝试一下在可能会遇到的乱码或者编码错误的问题。

比如说我们来爬取一个网页,就拿鱼c的首页来试水。先看看其前端的源码,是utf-8的。写个最简单的爬取脚本。

import urllib2

url=’https://www.fishc.com’

res=urllib2.urlopen(url)   

res=res.read()  #把抓取的网页的utf-8数据流读进去。

res=res.decode(‘utf-8’) #由于数据流是utf-8,因此要把utf-8解码成Unicode

#这里可以查看一下res的数据,可以发现有中文的地方就有/uxxx/uxxx啥的,这就是unicode字符…

#这也是编码成其他形式的第一步,必须要先解码变成unicode字符。再encode…

print res    #print 这个命令有自动转换成系统的”习惯编码”(例如上面说的win下是GBK系列,linux下是utf-8系列),GBK编码方式包含了所有中文,不会有乱码。

 

我们来试试另一种种方法:(接着上面res=res.read()往后)

res =res.encode(‘gbk’) #直接在utf-8的时候编码成gbk,由于win和linux系统默认编码方式都是ascii ,肯定是显示ascii cann’t decode… 

怎么回事?utf-8编码成gbk关ascii解码啥事?

其实是这样的,因为如果res这个字节流编码不是unicode就直接encode的话python会自动用默认的编码方式来decode成为unicode,刚才说过,py2编码(encode)必须要先把原来的格式解码(decode)成unicode,要经过这个”中间人”才能去编码成其他格式…然而网页的编码方式是utf-8,用ascii方式来decode怎么可能不报错呢…所以,我在网上找到了修改py默认编码方式的方法(一般改成utf-8比较好):

 

在linux下:

python安装目录:/etc/python2.x/sitecustomize.py

 

import sys

reload(sys)

sys.setdefaultencoding('utf-8')

try:

    import apport_python_hook

except ImportError:

   pass

else:

apport_python_hook.install()

如果在windows下:

可以在Python安装目录下的Lib/site-packages目录中,新建一个sitecustomize.py文件(也可以建在其它地方,然后手工导入,建在这里,每次启动Python的时候设置将自动生效),内容如下:

import sys

sys.setdefaultencoding('utf-8') #set default encoding to utf-8

然后可以查看到改变已经生效

import sys

sys.getdefaultencoding()

'utf-8'

此时运行程序,如果仍然报告之前的错误,只需要显示地设定输出的编码

print s.encode('utf-8')

就可以看到正确显示。

本人亲测有效!

改了默认编码方式以后,只要网页的编码方式和修改的默认编码方式相同,就可以直接encode,不需要decode这个步骤,因为这个步骤py会自动做好,代码如下:

res =res.read()

res.encode(‘gbk’) #在linux下可以这样,不过经常会看到gbk cann’t encode \uxxx....这只是gbk储存的字符集没有utf-8多,所以用gbk去编码unicode的话可能会出现”这个词不懂”的现象,一般都是用utf-8来编码gbk的,就不会”不懂”了,这个例子要是换成网站是gbk编码的就好了(反过来就行),但是gbk的网站比较少,只是例子问题,了解原理就OK...

在win下直接print res就相当于encode(‘gbk’)了...

 

前面讲的是用urllib2库中的中文编码问题,下面讲一下requests库中的中文编码问题…

还是用那个例子

import requests

url=’https://www.fishc.com’

res=requests.get(url)

print res.content

这个用print res.content不会有任何问题,但是如果使用print res.text就有可能有问题...(如果你喜欢折腾的话就用res.text吧,改一个默认编码方式就行)

这种情况输入可能会有乱码,因为res.text是unicode编码…然后直接print res.text就会以默认的编码方式输出,这个默认的编码方式是ISO-8859-1...应该是requests库默认的,可以用res.encoding来查看其方式…一般都是'ISO-8859-1'

我们可以改变其默认的方式:

res.encoding=’utf-8’

改成utf-8之后再试试res.text就没有乱码了…

我看官方的文档是说response.text每次都会去访问response.encoding里的编码方式。所以说py2真的很多地方没有考虑到中文字符,连unicode字符集也是后面才加入的,一开始很长一段时间都是用ascii,谁让这玩意是美国人发明的呢….

 

还好py3中有一些地方已经默认了是utf-8的方式,不然还得像py2一样去修改…很多人一直在问新手应该学py2还是py3,我个人认为,py3对中文的支持是毋庸置疑的,论编程的方便是远超py2的,但是因为年龄还比较短,py2具体有的很多包可能py3还不太完善,而且书籍也不多,所以如果想造轮子的话还是建议用py2,就是得多折腾些..不过未来肯定是py3的,这点是肯定的,如果新版本还比不上旧版本那做出来还有什么意义…所以说选择还是看自己….


评论(3)
热度(1)
©adminlzzs'blog | Powered by LOFTER