Python知識(shí)分享網(wǎng) - 專業(yè)的Python學(xué)習(xí)網(wǎng)站 學(xué)Python,上Python222
Python 錯(cuò)誤:UnicodeEncodeError: 'gbk' codec can't encode character '\xa0' in position 3: illegal multibyte sequence
匿名網(wǎng)友發(fā)布于:2023-07-09 11:00:44
(侵權(quán)舉報(bào))

 

當(dāng)python要做編碼轉(zhuǎn)換的時(shí)候,會(huì)借助于內(nèi)部的編碼,轉(zhuǎn)換過(guò)程是這樣的:

 

原有編碼 -> 內(nèi)部編碼(UNICODE) -> 目的編碼

 

\xa0 是不間斷空白符 

我們通常所用的空格是 \x20 ,是在標(biāo)準(zhǔn)ASCII可見(jiàn)字符 0x20~0x7e 范圍內(nèi)。
而 \xa0 屬于 latin1 (ISO/IEC_8859-1)中的擴(kuò)展字符集字符,代表空白符nbsp(non-breaking space)
latin1 字符集向下兼容 ASCII ( 0x20~0x7e )。通常我們見(jiàn)到的字符多數(shù)是 latin1 的,比如在 MySQL 數(shù)據(jù)庫(kù)中。

這里也有一張簡(jiǎn)陋的Latin1字符集對(duì)照表

 

\u3000 是全角的空白符

根據(jù)Unicode編碼標(biāo)準(zhǔn)及其基本多語(yǔ)言面的定義, \u3000 屬于CJK字符的CJK標(biāo)點(diǎn)符號(hào)區(qū)塊內(nèi),是空白字符之一。它的名字是 Ideographic Space ,有人譯作表意字空格、象形字空格等。顧名思義,就是全角的 CJK 空格。它跟 nbsp 不一樣,是可以被換行間斷的。常用于制造縮進(jìn), wiki 還說(shuō)用于抬頭,但沒(méi)見(jiàn)過(guò)。

這里還有一個(gè) Unicode.org 上關(guān)于 CJK 標(biāo)點(diǎn)符號(hào)塊的字符代碼表。

在讀取文件的時(shí)候,可以讓codecs來(lái)代勞。

 

codecs讀文件

results.txt

 

兩部委:到2020年底重點(diǎn)城市生活垃圾得到有效分類(圖)
英雄惜英雄! 傳奇為格策叫冤:已盡力不應(yīng)被批
中華關(guān)愛(ài)失能老兵和老人公益行活動(dòng)啟動(dòng)儀式在京舉行(組圖)
國(guó)安酷暑作戰(zhàn)滿意拿分 謝峰:上半場(chǎng)少補(bǔ)一次水
國(guó)內(nèi)首家省級(jí)民營(yíng)投資平臺(tái)在無(wú)錫揭牌成立
5月外匯供求進(jìn)一步趨向平衡 跨境資金流出壓力緩解

 

#-*- coding: UTF-8 -*-
import codecs
# 第三個(gè)參數(shù)可以為r只讀 w只寫 a附加 r+讀寫
cf = codecs.open("results.txt", "r", "UTF-8")
s = cf.read()
print s.encode("GBK", 'ignore')
cf.close()

 

如果報(bào)以下錯(cuò)誤:

 

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

 

是因?yàn)閃indows cmd默認(rèn)是GBK(CP936)編碼,有部分Unicde的字符無(wú)法編碼為GBK,所以可以把這些字符替換為空格,或者忽略掉。

方式1:string.replace(u'\xa0', u' ')

方式2:print "非法字符\xa0".encode("GBK", 'ignore');

 

codecs從UTF-8轉(zhuǎn)換為GBK格式

 

#-*- coding: UTF-8 -*-

import sys
reload(sys)
# 設(shè)置系統(tǒng)默認(rèn)編碼
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編碼的字符串轉(zhuǎn)換為GBK編碼,并忽略掉無(wú)法編碼的字符。
cwf.write(s.encode("gbk", 'ignore'))
cwf.flush()
cwf.close()

 

如果不加sys.setdefaultencoding(“gbk”)報(bào)錯(cuò):

 

使用編碼器

 

#-*- coding: UTF-8 -*-
import codecs

# 創(chuàng)建gb2312編碼器 
cgb   =  codecs.lookup("gb2312")

# 創(chuàng)建utf-8編碼器
# lookup函數(shù)返回一個(gè)包含四個(gè)元素的TUPLE
cutf8  =  codecs.lookup("utf-8")

print cutf8[0]
# <built-in function utf_8_encode>
# 同 codecs.getencoder("utf-8")

print cutf8[1]
# <function decode at 0x0000000002A20978>
# 同 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 = "我愛(ài)北京天安門"

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

# 從單字節(jié)到多字節(jié)叫做decoding
utest = cutf8.decode(stest)
# (u'\u6211\u7231\u5317\u4eac\u5929\u5b89\u95e8', 21)

print utest[0], type(utest[0])
# 我愛(ài)北京天安門 <type 'unicode'>

# 從多字節(jié)到單字節(jié)叫做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])
# 我愛(ài)北京天安門 <type 'str'>

 

從單字節(jié)到多字節(jié)叫做decoding,從多字節(jié)到單字節(jié)叫做 encoding。

 

為什么從 unicode 轉(zhuǎn) str 是 encode,而反過(guò)來(lái)叫 decode?

因?yàn)?Python 認(rèn)為 16 位的 unicode 才是字符的唯一內(nèi)碼,而大家常用的字符集如 gb2312,gb18030/gbk,utf-8,以及 ascii 都是字符的二進(jìn)制(字節(jié))編碼形式。把字符從 unicode 轉(zhuǎn)換成二進(jìn)制編碼,當(dāng)然是要 encode。

反過(guò)來(lái),在 Python 中出現(xiàn)的 str 都是用字符集編碼的 ansi 字符串。Python 本身并不知道 str 的編碼,需要由開(kāi)發(fā)者指定正確的字符集 decode。

轉(zhuǎn)載自:https://blog.csdn.net/sky0Lan/article/details/116527261