Mrli
别装作很努力,
因为结局不会陪你演戏。
Contacts:
QQ博客园

写爬虫过程中碰到的编码问题

2019/09/15 爬虫 Python
Word count: 1,638 | Reading time: 7min

写爬虫过程中碰到的编码问题

遇到 ’ \uxxxx ’ 的16进制字符串编解码问题,使用unicode-escape解决之。

实际上,在将unicode存储到文本的过程中,还有一种存储方式,不需要将unicode转换为实际的文本存储字符集,而是将unicode的内存编码值进行存储,读取文件的时候再反向转换回来,是采用:unicode-escape的转换方式。

将unicode的内存编码值进行存储,读取文件时在反向转换回来。这里就采用了unicode-escape的方式

1
2
3
4
5
6
7
8
print(u'中文测试'.encode('utf-8'))
print('中文测试'.encode('utf-8'))
print(u'中文测试'.encode('unicode-escape'))
print('中文测试'.encode('unicode-escape'))
==> b'\xe4\xb8\xad\xe6\x96\x87\xe6\xb5\x8b\xe8\xaf\x95'
==> b'\xe4\xb8\xad\xe6\x96\x87\xe6\xb5\x8b\xe8\xaf\x95'
==> b'\\u4e2d\\u6587\\u6d4b\\u8bd5'
==> b'\\u4e2d\\u6587\\u6d4b\\u8bd5'

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
2
3
4
5
6
7
import sys 
sys.stdout.encoding 
在 Windows 下,如果你的系统是简体中文,一般输出会是 cp936 

import codecs 
codecs.lookup('cp936').name 
'gbk'

这就是在 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
2
3
4
5
6
7
8
9
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Console\%SystemRoot%_system32_cmd.exe]
"CodePage"=dword:0000fde9
"FontFamily"=dword:00000036
"FontWeight"=dword:00000190
"FaceName"="Consolas"
"ScreenBufferSize"=dword:232900d2
"WindowSize"=dword:002b00d2

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.

< PreviousPost
Pythonanywhere解决链接Mysql问题(部署flask)
NextPost >
Shell脚本基础
CATALOG
  1. 1. 写爬虫过程中碰到的编码问题
    1. 1.0.1. 遇到 ’ \uxxxx ’ 的16进制字符串编解码问题,使用unicode-escape解决之。
    2. 1.0.2. 总结:
  2. 1.1. Python中编码问题
  3. 1.2. 如果CMD命令行是gbk编码的,则输出的utf-8字符有些也显示不了
    1. 1.2.1. Win10 临时修改cmd命令行窗口UTF-8编码
    2. 1.2.2. Windows 控制台使用注册表永久修改编码问题
      1. 1.2.2.1. 方法一:
      2. 1.2.2.2. 方法二:(亲测有效)