1. 程式人生 > >UnicodeEncodeError:'gbk'編解碼器無法對位置43的字元u'\ u200e'進行編碼:非法multib

UnicodeEncodeError:'gbk'編解碼器無法對位置43的字元u'\ u200e'進行編碼:非法multib

原連結:HTTP://www.crifan.com/unicodeencodeerror_gbk_codec_can_not_encode_character_in_position_illegal_multibyte_sequence/

【問題】

蟒蛇中已獲取網頁:

的HTML原始碼,其時UTF-8編碼的。

提取出其標題部分:

?
12345<span class="link_title"><a href="/hfahe/article/details/5494895">在2008 Beijing Perl 大會的演講-使用Mason開發高效能的Web站點‎ </a></span>

中的標題文字:

在2008北京Perl大會的演講 - 使用梅森開發高效能的網站站點

然後用:

titleUni = unicode(titleHtml,“UTF-8”);

titleUni = titleHtml.decode(“UTF-8”);

將其解碼成Unicode的,但是卻會出錯:

UnicodeEncodeError:'gbk'編解碼器無法對字元u'\ u200e'進行位置43:非法多位元組序列

【解決過程】

1.Python的編碼問題,GB18030,UTF-8,Unicode的等問題,之前遇到過很多次了,也就解決了。此處很奇怪的是,

類似的其他的網頁,比如:

等,對應提取出來的內容,都是可以正常解碼為統一的。

因為本身其編碼的確是UTF-8的。

2.去試了試用chardet.detect分析其真正編碼的,得到的結果是:

encInfo = {'confidence':0.99,'encoding':'utf-8'}

也是和其他網頁內容得到的結果是一樣的。

3.此問題覺得很詭異的是,本身呼叫UTF-8去解碼,但是解碼出錯卻提示的是GBK的,而不是UTF-8相關解碼出錯。

4.找了些其他帖子:

但是討論的都是關於從統一編碼為GBK或GB2312,然後出錯的。

而我這裡的錯誤是,本身內容是UTF-8的,然後想要還原為Unicode的,結果卻提示GBK解碼錯誤的...

5.這裡:探索UTF-8中文編碼的BOM問題標記提到了,可能是由於UTF-8的BOM造成的不能正常解碼,所以試著去將返回的HTML匯出為HTML檔案,然後用記事本++檢視,結果還是沒看出是否有BOM,反正是文字內容,都可以檢視到的。

然後也試了類似程式碼:

titleUni = titleHtml [1:]。decode(“UTF-8”);

titleUni = titleHtml [2:]。decode(“UTF-8”);

但是都還是不行。

在後來這裡也。看到了,關於UTF-8的BOM的問題的解釋,但同樣不是我要的。

s.decode('gbk','ignore')。encode('utf-8')

然後才想起來,之前是看到過類似的解釋,即新增忽略來忽略非法的字元,然後又參考:

然後去找了對應語法:

海峽。解碼 [ 編碼 [,  錯誤 ]] 

使用註冊編碼的編碼解碼器解碼字串  。 編碼  預設為預設的字串編碼。  可能會給出錯誤來設定不同的錯誤處理方案。預設值是  'strict',這意味著編碼錯誤會引發UnicodeError其他可能的值是  'ignore',  'replace'  和通過codecs.register_error()註冊的任何其他名稱  ,請參見  編解碼器基類

2.2版本中的新功能。

在版本2.3中進行了更改:添加了對其他錯誤處理方案的支援。

在2.7版本中進行了更改:添加了對關鍵字引數的支援。

試了:

titleUni = titleHtml.decode(“UTF-8”,'ignore');

和:

titleUni = titleHtml.decode(“UTF-8”,'replace');

但是結果仍是:

列印“titleUni =”,titleUni;

會出現上述“'gbk'codec can not encode”的錯誤。

但是後來無意間發現,在列印titleUni之前,添加了一行除錯程式碼:

列印“len(titleUni)=”,len(titleUni);

卻是可以正常列印的,這就說明,此處的titleUni變數,正常解碼為統一的值了,即上述解碼是正常的。

然後又重新試了試,之前的:

titleUni = titleHtml.decode(“UTF-8”);

結果也是一樣的,即print“len(titleUni)=”,len(titleUni);也是可以正常輸出的。

然後此時才明白,原來出現'gbk'codec can not encode“的錯誤的根本原因是,對於前面的,不論是用

titleHtml.decode(“UTF-8”);

還是

titleHtml.decode(“UTF-8”,'忽略');

還是

titleHtml.decode(“UTF-8”,'替換');

都是可以得到正常的titleUni的統一字元的,然後對於此統一的字元,需要打印出來的話,由於本地系統是Win7的中的CMD,預設內碼表是CP936,即GBK的編碼,所以需要先將上述的統一的titleUni先編碼為GBK,然後再在cmd中顯示出來,然後由於titleUni中包含一些GBK中無法顯示的字元,導致此時提示“'gbk'編解碼器無法編碼”的錯誤的。

【總結】

對於此(類)問題:

(1)出現UnicodeEncodeError - >說明是Unicode編碼時候的問題;

(2)'gbk'codec can not encode character - >說明是將Unicode字元編碼為GBK時候出現的問題;

此時,往往最大的可能就是,本身的Unicode型別的字元中,包含了一些無法轉換為GBK編碼的一些字元。

解決辦法是:

  • 方案1:

在對Unicode的字元編碼時,新增忽略引數,忽略無法無法編碼的字元,這樣就可以正常編碼為GBK了。

對應程式碼為:

gbkTypeStr  = unicodeTypeStr.encode(“ GBK ”,  'ignore');
  • 方案2:

或者,將其轉換為GBK編碼的超集GB18030(即,GBK是GB18030的子集):

gb18030TypeStr  = unicodeTypeStr.encode(“ GB18030 ”);

對應的得到的字元是GB18030的編碼。

【題外話】

對於上述中,將原先的UTF-8的字元轉換為Unicode的的時候,其實更加安全的做法,也可以將:

titleUni = titleHtml.decode(“UTF-8”);

替換為:

titleUni = titleHtml.decode(“UTF-8”,'ignore');

這樣可以實現,即使對於那些,相對來說是無關緊要的一些特殊字元,也可以成功編碼,避免編碼出錯,提高程式的健壯性。