1. 程式人生 > >解決python3 UnicodeEncodeError: 'gbk' codec can't encode character '\xXX' in position XX

解決python3 UnicodeEncodeError: 'gbk' codec can't encode character '\xXX' in position XX

從網上抓了一些位元組流,想打印出來結果發生了一下錯誤:

UnicodeEncodeError: 'gbk' codec can't encode character '\xbb' in position 8530: illegal multibyte sequence

程式碼

import urllib.request
res=urllib.request.urlopen('http://www.baidu.com')
htmlBytes=res.read()
print(htmlBytes.decode('utf-8'))

錯誤資訊讓人很困惑,為什麼用的是'utf-8'解碼,錯誤資訊卻提示'gbk'錯誤呢?

不僅如此,從百度首頁的html中發現以下程式碼:

<meta http-equiv="content-type" content="text/html;charset=utf-8">

這說明網頁的確用的是utf-8,為什麼會出現Error呢?

在python3裡,有幾點關於編碼的常識

1.字元就是unicode字元,字串就是unicode字元陣列

如果用以下程式碼測試,

print('a'=='\u0061')

會發現結果為True,足以說明兩者的等價關係。

2.str轉bytes叫encode,bytes轉str叫decode,如上面的程式碼就是將抓到的位元組流給decode成unicode陣列

我根據上面的錯誤資訊分析了位元組流中出現\xbb的地方,發現有個\xc2\xbb的特殊字元»,我懷疑是它無法被解碼。

用以下程式碼測試後

print(b'\xc2\xbb'.decode('utf-8'))
它果然報錯了:UnicodeEncodeError: 'gbk' codec can't encode character '\xbb' in position 0: illegal multibyte sequence

上網找了下utf-8編碼表,發現的確特殊字元»的utf-8形式就是c2bb,unicode是'\u00bb',為什麼無法解碼呢。。。

仔細看看錯誤資訊,它提示'gbk'無法encode,但是我的程式碼是utf-8無法decode,壓根牛頭不對馬嘴,終於讓我懷疑是print函數出錯了。。於是立即有了以下的測試

print('\u00bb')
結果報錯了:UnicodeEncodeError: 'gbk' codec can't encode character '\xbb' in position 0: illegal multibyte sequence

原來是print()函式自身有限制,不能完全列印所有的unicode字元。

知道原因後,google了一下解決方法,其實print()函式的侷限就是Python預設編碼的侷限,因為系統是win7的,python的預設編碼不是'utf-8',改一下python的預設編碼成'utf-8'就行了

import io
import sys
import urllib.request
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf8') #改變標準輸出的預設編碼
res=urllib.request.urlopen('http://www.baidu.com')
htmlBytes=res.read()
print(htmlBytes.decode('utf-8'))

執行後不報錯了,但是居然有好多亂碼(英文顯示正常,中文則顯示亂碼)!!又一陣折騰後發現是控制檯的問題,具體來說就是我在cmd下執行該指令碼會有亂碼,而在IDLE下執行卻很正常。

由此我推測是cmd不能很好地相容utf8,而IDLE就可以,甚至在IDLE下執行,連“改變標準輸出的預設編碼”都不用,因為它預設就是utf8。如果一定要在cmd下執行,那就改一下編碼,比如我換成“gb18030”,就能正常顯示了:

sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030')         #改變標準輸出的預設編碼
最後,附上一些常用的和中文有關的編碼的名稱,分別賦值給encoding,就可以看到不同的效果了:
編碼名稱 用途
utf8 所有語言
gbk 簡體中文
gb2312 簡體中文
gb18030 簡體中文
big5 繁體中文
big5hkscs 繁體中文