写爬虫过程中碰到的编码问题
遇到 ’ \uxxxx ’ 的16进制字符串编解码问题,使用unicode-escape
解决之。
实际上,在将unicode存储到文本的过程中,还有一种存储方式,不需要将unicode转换为实际的文本存储字符集,而是将unicode的内存编码值进行存储,读取文件的时候再反向转换回来,是采用:unicode-escape的转换方式。
将unicode的内存编码值进行存储,读取文件时在反向转换回来。这里就采用了unicode-escape的方式
1 | print(u'中文测试'.encode('utf-8')) |
ASCII码只有128个字符,符合英文,一个英文字符只用1个字节(最高位恒为0)
ANSI:面向中文编码的GBK、GB2312是ANSI码的一种,ANSI码是对ASCII的拓展,所以一个英文只用一个字节,而中文需要拓展ASCII,所以用到两个字节。 0x80~0xFFFF =>2**16
Unicode编码:为了解决不同国家ANSI编码的冲突问题,最常用的是用两个字节表示一个字符 。但是这样的话,原本可以用一个字节存储的英文字母在Unicode里面必须存两个字节,这就产生了浪费。那么有没有一种既能消除乱码,又能避免浪费的编码方式呢?===>答案就是UTF-8 。000000 -10FFFF
1
2 > UNICODE 的范围是 0x0000 - 0xFFFF 共6万多个字符,其中光汉字就占用了4万多个
>
UTF-8编码:当字符在ASCII码的范围时,就用一个字节表示 ,所以英文字符也只用一个字节,▲值得注意的是unicode编码中一个中文字符占2个字节,而UTF-8一个中文字符占3个字节。从unicode到uft-8并不是直接的对应,而是要过一些算法和规则来转换。utf-8长度是1-6个字节 (可变的)
Unicode编码(十六进制) | UTF-8 字节流(二进制) |
---|---|
000000-00007F | 0xxxxxxx |
000080-0007FF | 110xxxxx 10xxxxxx |
000800-00FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
010000-10FFFF | 11110xxx 10xxxxxx 10xxxxxx10xxxxxx |
超出10FFFF后,UTF-8与Unicode不再对应
总结:
UTF-8 vs GBK:
UTF-8版本虽然具有良好的国际兼容性,但中文需要比GBK/BIG5版本多占用50%的数据库存储空间,因此并非推荐使用,仅供对国际兼容性有特殊要求的用户使用。简单地说:对于中文较多的网站,适宜用GBK编码节省数据库空间。对于英文较多的网站,适宜用UTF-8节省数据库空间。
字符编码ANSI和ASCII区别、Unicode和UTF-8区别
Python中编码问题
在python中,unicode是内存编码集,一般我们将数据存储到文件时,需要将数据先编码为其他编码集,比如utf-8、gbk等。
读取数据的时候再通过同样的编码集进行解码即可。
但是其实还有一种unicode-escape编码集,他是将unicode内存编码值直接存储:
在使用python3的requests模块时,发现获取响应有两种方式
- 其一,为文本响应内容, r.text是Unicode的响应内容
- 其二,为二进制响应内容,r.content是二进制的响应内容
Python2 的编码问题一直非常让人恼火,不过你的问题稍微简单一些。
在交互式命令模式(Interactive shell)下,可以这样来明白你遇到的问题的根源:
1 | import sys |
这就是在 Windows 终端里面使用的编码。在 print 的时候,无论字符串源采取什么样的编码,最终输出的字符串的编码必须跟 shell 的编码一致,也就是说:
print some_string
Python 会做这样一个动作:
codecs.encode(some_string, coding, errors=‘strict’)
在你遇到的情况下,some_string 是一个 unicode 字符串,coding 是 gbk。由于你的 unicode 字符串里面包含 gbk 字符集里面没有的字符,Python 就会抛出一个 UnicodeEncodeError.
对于输出到文件中情况是类似的,Python2 的 open() 函数不会传入 encoding,以 ‘w’ 方式打开文件,如果写入 unicode 字符串,Python 会获取当前默认的编码,然后以此种编码把字符串写入文件。可惜的是,“默认编码”只是 Python 自己默认的,在 Objects/unicodeobject.c 中,用一个全局变量 unicode_default_encoding 来表示默认的编码:
/* Default encoding to use and assume when NULL is passed as encoding
parameter; it is initialized by _PyUnicode_Init(). Always use the PyUnicode_SetDefaultEncoding() and
PyUnicode_GetDefaultEncoding() APIs to access this global.
static char unicode_default_encoding[100 + 1] = "ascii";
这个值在 Python 中有C接口(PyUnicode_SetDefaultEncoding)去改变,但可惜的是没有 Python 层的接口。
所以在调用到类似 file.write(some_string) 的时候,首先会有这样的编码过程:
codecs.encode(some_string, coding, errors=‘restrict’)
当你的 some_string 是一个 unicode 字符串,并且包含 ascii 字符串不存在的字符时,就会抛出一个 UnicodeEncodeError。
所以,为了解决这个问题,可以这么处理:
(1) 在 Windows shell 下面:
>>> print some_string.encode(‘gbk’, errors=‘ignore’) # replace 也可,只要不是 restrict
(2) 在写入文件时,两种方法:
a. 忽略不存在的字符,同(1)
>>> f = open(filename, ‘w’)
>>> f.write(some_string.encode(‘gbk’, errors=‘ignore’)
b. byte 方式写入:
>>> f = open(filename, ‘wb’)
>>> f.write(some_string.encode(‘utf-8’))
a 会损失字符,b 不会。
来自http://www.newsmth.net/nForum/#!article/Python/124657
如果CMD命令行是gbk编码的,则输出的utf-8字符有些也显示不了
Win10 临时修改cmd命令行窗口UTF-8编码
只作用于当前打开的窗口
进入cmd窗口后,直接执行“chcp 65001”,执行完后,cmd的编码格式就是UTF-8
Windows 控制台使用注册表永久修改编码问题
方法一:
1.在cmd中输入regedit
进入注册表
2.找到HKEY_CURRENT_USER\Console\%SystemRoot%_system32_cmd.exe
3.新建一个 DWORD(32位值),命名为CodePage,值设为65001
4.已有CodePage的话,修改它,改为十进制,65001
方法二:(亲测有效)
1.新建一个cmd.reg注册表文件:
2.内容输入如下:
1 | Windows Registry Editor Version 5.00 |
3.双击运行
Author: Mrli
Link: https://nymrli.top/2018/11/08/写爬虫过程中碰到的编码问题/
Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.