Python编码问题学习笔记

0x01 现在计算机系统通用的字符编码工作方式:

在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。python语言有两种不同的字符串,一个用于存储文本,一个用于存储原始字节。文本字符串(str)内部使用Unicode存储,字节字符串(byte)存储原始字节并显示ASCI

0x02 Unicode的问题

Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储,所以,内存的数据都用Unicode码表表示,因为它的广泛性,可以显示一切字符码,但是,如果存储就出现问题了,参考下面的一段话:

两个严重的问题,第一个问题是,如何才能区别unicode和ascii?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。
它们造成的结果是:1)出现了unicode的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示unicode。2)unicode在很长一段时间内无法推广,直到互联网的出现。

0x03 Python3中的​encode和decode

Python3中字符编码经常会使用到decode和encode函数。特别是在抓取网页中,这两个函数用的熟练非常有好处。我的理解,encode的作用,使我们看到的直观的字符转换成计算机内的字节形式。decode刚好相反,把字节形式的字符转换成我们看的懂的、直观的、“人模人样”的形式

0x04 如何查看str在内存中的unicode码

字符在计算机的内存中统一是以Unicode编码的。只有在字符要被写进文件、存进硬盘或者从服务器发送至客户端(例如网页前端的代码)时会变成utf-8。如何把字符以Unicode的字节形式表现出来,露出它在内存中的庐山正面目?这里有个照妖镜:

xxxx.encode/decode(‘unicode-escape’),

>>> s="中文"
>>> s.encode('unicode-escape') # 通过encode得到了“中文”的unicode字节码
b'\\u4e2d\\u6587'
>>> b="\u4e2d" # 把“中”的unicode码赋值给b,注意b是str,这就是str在内存的真实面目了
>>> print(b)

0x05 unicode码在python里有两种表示方式:

u’字符串’或者’\u四位十六进制数’。它们是等价的,而且都是str对象。注意,’\u四位十六进制数’与’\u四位十六进制数’并不相等,’\u四位十六进制数’=’\’(斜杠本身是转义字符要经过转义表示)+’u四位十六进制数’。

Unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。UTF-8 就是在互联网上使用最广的一种 Unicode 的实现方式,它定义了Unicode符号集的二进制代码如何保存,具体的保存方式参考下面的链接:

[参考链接][http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html]

0x06 import chardet 这个模块可以帮助检测当前的字节流编码

>>> s='abc'
>>> s.encode()
b'abc'
>>> chardet.detect(s.encode())
{'encoding': 'ascii', 'language': '', 'confidence': 1.0}
>>> s='中文'
>>> chardet.detect(s.encode())
{'encoding': 'utf-8', 'language': '', 'confidence': 0.7525}