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