错误:UnicodeEncodeError: ‘gbk‘ codec can‘t encode character ‘\xa0‘

当python要做编码转换的时候,会借助于内部的编码,转换过程是这样的:

原有编码 -> 内部编码(UNICODE) -> 目的编码

 
 
   
   
   
   
  • 1
\xa0 是不间断空白符 

我们通常所用的空格是 \x20 ,是在标准ASCII可见字符 0x20~0x7e 范围内。
\xa0 属于 latin1 (ISO/IEC_8859-1)中的扩展字符集字符,代表空白符nbsp(non-breaking space)。
latin1 字符集向下兼容 ASCII ( 0x20~0x7e )。通常我们见到的字符多数是 latin1 的,比如在 MySQL 数据库中。

这里也有一张简陋的Latin1字符集对照表。

\u3000 是全角的空白符

根据Unicode编码标准及其基本多语言面的定义, \u3000 属于CJK字符的CJK标点符号区块内,是空白字符之一。它的名字是 Ideographic Space ,有人译作表意字空格、象形字空格等。顾名思义,就是全角的 CJK 空格。它跟 nbsp 不一样,是可以被换行间断的。常用于制造缩进, wiki 还说用于抬头,但没见过。

这里还有一个 Unicode.org 上关于 CJK 标点符号块的字符代码表。

在读取文件的时候,可以让codecs来代劳。

codecs读文件

results.txt

两部委:到2020年底重点城市生活垃圾得到有效分类(图)
英雄惜英雄! 传奇为格策叫冤:已尽力不应被批
中华关爱失能老兵和老人公益行活动启动仪式在京举行(组图)
国安酷暑作战满意拿分 谢峰:上半场少补一次水
国内首家省级民营投资平台在无锡揭牌成立
5月外汇供求进一步趋向平衡 跨境资金流出压力缓解
#-*- coding: UTF-8 -*-
import codecs
# 第三个参数可以为r只读 w只写 a附加 r+读写
cf = codecs.open("results.txt", "r", "UTF-8")
s = cf.read()
print s.encode("GBK", 'ignore')
cf.close()

如果报以下错误:

UnicodeEncodeError: 'gbk' codec can't encode character '\xa0' in position 268: illegal multibyte sequence

是因为Windows cmd默认是GBK(CP936)编码,有部分Unicde的字符无法编码为GBK,所以可以把这些字符替换为空格,或者忽略掉。

  • 方式1:string.replace(u'\xa0', u' ')
  • 方式2:print "非法字符\xa0".encode("GBK", 'ignore');
codecs从UTF-8转换为GBK格式
#-*- coding: UTF-8 -*-

import sys
reload(sys)
# 设置系统默认编码
sys.setdefaultencoding("gbk")
import codecs
crf = codecs.open("results.txt", "r", "UTF-8")
s = crf.read()
crf.close()
cwf = codecs.open("out.txt", "w", "gbk")
print type(s)
# 把UTF-8编码的字符串转换为GBK编码,并忽略掉无法编码的字符。
cwf.write(s.encode("gbk", 'ignore'))
cwf.flush()
cwf.close()

如果不加sys.setdefaultencoding(“gbk”)报错:

UnicodeDecodeError: 'utf8' codec can't decode byte 0xd6 in position 2: invalid continuation byte

sys.setdefaultencoding(“gbk”) 是把系统默认编码方式设置为GBK。

使用编码器
#-*- coding: UTF-8 -*-
import codecs

# 创建gb2312编码器 
cgb   =  codecs.lookup("gb2312")

# 创建utf-8编码器
# lookup函数返回一个包含四个元素的TUPLE
cutf8  =  codecs.lookup("utf-8")

print cutf8[0]
# 
# 同 codecs.getencoder("utf-8")

print cutf8[1]
# 
# 同 codecs.getdecoder("utf-8")

print cutf8[2]
# encodings.utf_8.StreamReader
# 同 codecs.getreader("utf-8")

print cutf8[3]
# encodings.utf_8.StreamWriter
# 同 codecs.getwriter("utf-8")

stest = "我爱北京天安门"

print len(stest), stest, type(stest)
# 21 鎴戠埍鍖椾含澶╁畨闂?

# 从单字节到多字节叫做decoding
utest = cutf8.decode(stest)
# (u'\u6211\u7231\u5317\u4eac\u5929\u5b89\u95e8', 21)

print utest[0], type(utest[0])
# 我爱北京天安门 

# 从多字节到单字节叫做encoding
gtest = cgb.encode(utest[0])
# ('\xce\xd2\xb0\xae\xb1\xb1\xbe\xa9\xcc\xec\xb0\xb2\xc3\xc5', 7)

print gtest[0], type(gtest[0])
# 我爱北京天安门 

从单字节到多字节叫做decoding,从多字节到单字节叫做 encoding。

为什么从 unicode 转 str 是 encode,而反过来叫 decode?

因为 Python 认为 16 位的 unicode 才是字符的唯一内码,而大家常用的字符集如 gb2312,gb18030/gbk,utf-8,以及 ascii 都是字符的二进制(字节)编码形式。把字符从 unicode 转换成二进制编码,当然是要 encode。

反过来,在 Python 中出现的 str 都是用字符集编码的 ansi 字符串。Python 本身并不知道 str 的编码,需要由开发者指定正确的字符集 decode。

你可能感兴趣的:(python)