“Most programmers think of strings as series of characters used to represent textual data”—— Learning Python.
如果仅是在终端上Run代码呈现文本,确实不需要考虑编码问题,但现实是文本数据经常需要被传送,被他人的代码读取。
涉及到文本的传输与存储,就涉及到了字符的编/解码:
将字符串按指定字符映射集导出到其他介质中的字节序列的过程,称为编码 (Encoding);将编码过的字节序列从其他介质按指定字符映射集还原成字符串的过程,称为解码 (Decoding)。
在编/解码的对称中,唯一需要明确的就是字符集。字符集是一张映射表,规定了单个字符在内存中的存储代码。比如支持最为广泛的ASCII字符集:
ASCII字符集由于使用单字节存储,表示能力有限。这也促成了各式各样字符集的出现,其中最为著名的莫过于Unicode。Unicode字符集以支持多语言环境为设计出发点,可以将它看成是ASCII字符集的超集:
但是这些,和编程有什么关系?
我大概能知道,在Python 2 中:
- string 有两种类型:str( ASCII字符集 ) 和 unicode(Non-ASCII字符集)
- str 是默认的文本表示容器
- 如果要使用unicode,需要显示声明
- 源文件默认也是使用ASCII编码存储的,需要加# -*- coding: -*- 头来声明它的编码
- 默认的运行时环境,是基于 ASCII字符集的,除非用 sys.setdefaultencoding 设置环境字符集
所谓“乱码”问题,归根到底是编解码使用的字符集不对称,可以从上述列表项中找到对应解决方法。
这两天在拿Scrapy练手,不巧也遇到了中文页面解码“乱码”。在一个类似这样的页面中:
1 2 |
<meta http-equiv="Content-Type" content="text/html; charset=gb2312"/> <title>《大卫·贝克汉姆》([英]贝克汉姆)【摘要 书评 试读】- ****</title> |
CharDet 检测报告它的编码为”GB2312″,但使用 “GB2312″进行解码转换,却会出现 “illegal byte sequence” 之类的错误——这个页面不诚实,它使用了”GB2312″ 范围之外的字符。对付这种流氓页面,需要”GB2312″的超集来处理它,比如”GBK” (知乎上关于中文字符集的讨论) 。
为此,写了一个苟且的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import chardet import sys def convert_utf(body, text): content_type = chardet.detect(body) encoding = content_type['encoding'] if encoding == 'GB2312': encoding = 'GBK' if encoding != 'UTF-8': reload(sys) sys.setdefaultencoding(encoding) text = text.decode(encoding, 'ignore') text = text.encode('utf-8') return text |
打赏作者
您的支持将激励我继续创作!
这个页面不诚实 哈哈~
这个页面不诚实~