从python2更新到python3,相信每个人都遇到过爬取网页编码错乱,编码转码混淆等问题,在这里,笔者详细说明一下python2与python3之间的字符编码问题,也是个人在使用过程中的一些总结。
1. 什么是字符编码: 计算机里所有数据,本质都是二进制表示。
先带大家来看下什么是编码
这里用的是python3环境,python3环境默认字符串的字符类型是str,默认编码类型是Unicode,字符类型和编码类型是不一样的。在上图chr是找到数字对应的ASCII表里面的字符
编码表:将计算机里的二进制数据,通过编码表对应,转换为人类可以看懂的字符。
所以97 ASCII ‘a’ ASCII就是编码类型,常用编码类型还有Unicode、utf-8、gbk,他们的发展历程是这样的
最早的计算机是美国人发明的,最开始设计编码表的时候,只考虑的美国的语言习惯(数据、字母和普通字符)0~127, ASCII 美国标准信息交换码
后来计算机开始普及全球,欧洲 Latin-1、 中国简体中文 GB2312、繁体中文 Big5、日本Shift_JIS,0~127不够用了,各个国家开始指定自己的编码表(在ASCII表基础上进行扩展,所以前127个都是一样的) 导致各个国家的编码不统一,文化交流不方便,文本内容传输做编码转换很麻烦。
于是国标组织指定了一个大一统的编码表:Unicode 万国码(给世界上每个字符,单独指定了一个二进制,再通过Unicode编码表转换)
Unicode里每个字符占用4个字节(不够4个字节,前面补0),所以Unicode浪费空间。
'a' == 00000000 00000000 00000000 01100001
于是在Unicode基础上做了升级,UTF-8(可变长的Unicode),可以根据字符类型来指定字节空间(尽可能减少空间占用)
在UTF-8里,一个字母1个字节,一个汉字3个字节 ; 在GBK里,一个字母1个字节,一个汉字2个字节(在简体中文处理GBK优于UTF-8)
UTF-8 也是当前世界上最流行的编码表处理方案,所有的Linux终端默认编码是UTF-8, 90%的网页都是UTF-8,简体中文的Windows终端默认编码是 GBK,也称为 CP936 (code page 936)
现在再来说python2与python3编码的区别
Python3 类型 和 编码:
str 类型字符串 是 Unicode编码
bytes 类型字符串 是 非Unicode(GBK、utf-8、jpg、mp4、mp3)
Python2 类型 和 编码:
str 类型字符串 是 非Unicode编码(GBK、utf-8、jpg、mp4、mp3)
unicode 类型字符串 是 Unicode编码
那么问题就来了,如果遇到字符串编码不一致,如何转为同一个编码统一处理?
解决办法:任何操作系统、任何编程语言、任何编码字符串,都可以和Unicode互相转换。
在python2与3中需要用到encode编码与decode解码
在python3中str类型字符串‘unicode_str’编码是unicode编码,这个是万能编码,可以通过utf-8编码为utf-8编码的bytes类型
反过来,bytes类型通过utf-8解码还成为原来的字符串。
同样也可以用GBK编码
到了这里可能就有疑惑了,为什么通过GBK编码再用UTF-8解码还原后是一样的,是因为输入的是英文,而英文的编码都是一样的,所以重点来了
将中文使用utf-8编码再用GBK解码
到这里是否就清楚了一些,为什么在爬取网页下载到本地的时候会出现乱码,是因为网页可能采用GBK编码,而python3对下载的网页默认使用UTF-8解码
那么python2的环境看看,值得注意Python2的终端创建字符串,Windows 是 GBK, Linux 是 UTF-8, 为 str 类型(Python2的 str 是 非Unicode)我用的是mac,是UTF-8编码,而Python2默认解释器编码为ascii,所以来看看
是不是有点奇怪,为什么在python2输入字符串再使用utf-8编码会报错,而解码不报错。再来看看
到了这里是否能明白了,因为所有的编码解码出问题基本都是非英文字符。而几大编码是包含关系,unicode最大,可以使用其他编码,而其他编码使用都可以解码为unicode类型,再看
在python2中str类型默认编码类型为ascii,但是中文不在ascii码范围之内,因为在终端输入的编码类型不为ascii,根据终端环境为GBK或者utf-8,也是非unicode,所有非unicode编码均可以解码为unicode编码,因为unicode编码包含了所有编码。所有的编码与解码。会根据当前环境的不同而产生不同的效果,具体都可以自己多测试测试就可以明白,但是需要注意一点,在写入文件的时候一定要注意编码统一,如果追加的编码类型不一样会导致整个文件的编码错误,除非手动切分再重新编码才能还原。