1. 程式人生 > >Python3解決UnicodeDecodeError: 'utf-8' codec can't decode byte..問題 終極解決方案

Python3解決UnicodeDecodeError: 'utf-8' codec can't decode byte..問題 終極解決方案

Python3解決UnicodeDecodeError: 'utf-8' codec can't decode byte..問題 終極解決方案

2017年10月06日 13:19:42 閱讀數:52021 標籤: python 更多

個人分類: 程式設計探討 python

版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/wang7807564/article/details/78164855

0x00 問題引出:

 


最近在做一個買房自動化分析Python指令碼,需要爬取網頁。
在使用urllib獲取reqest的response的時候,還要進行解碼。
見語句:

result = res.decode('utf-8')
  • 1

當執行該語句的時候,會造成異常:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe5 in position 103339: invalid continuation byte
  • 1

0x01 問題分析

該情況是由於出現了無法進行轉換的 二進位制資料 造成的,可以寫一個小的指令碼來判斷下,是整體的字符集引數選擇上出現了問題,還是出現了部分的無法轉換的二進位制塊:

#python3
#以讀入檔案為例:
f = open("data.txt","rb")#二進位制格式讀檔案
while True:
    line = f.readline()
    if not line:
        break
    else:
        try:
            #print(line.decode('utf8'))
            line.decode('utf8')
            #為了暴露出錯誤,最好此處不print
        except:
            print(str(line))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

手寫了一段程式碼,可以通過這段程式碼的輸出來判斷哪裡出現了問題。

  • 1.如果輸出的程式碼都是hex形式的,可能就是你選擇的解碼字符集出現了錯誤。 對於python2.7版本的來說,網上有使用這樣一種看上去很霸氣,其實很low的方式,來處理:
#coding=utf8
import sys
reload(sys)
sys.setdefaultxxxx("utf8")
  • 1
  • 2
  • 3
  • 4

其實,這可以看作是python2系列版本的小bug,需要自行重新設定一下預設的編碼字符集,如果還要這麼設定的話,decode()的引數還拿來幹嘛。
所以,在python3版本中,就已經取消了這個方法。

  • 2.如果是字符集出現錯誤,建議多選擇幾種字符集測試一下: 選擇的經驗是: 如果是爬取到的網頁檔案,可以檢視網頁檔案的meta標籤下的charset屬性值。

例如:

<meta charset="UTF-8">
  • 1

也可以使用notepad++開啟,檢視下右下角的部位,會指示該檔案是那種編碼。

  • 3.有的情況,是這樣的,整個檔案是好的,如果用notepad++開啟後,能夠看到檔案是可以開啟的,似乎什麼問題都沒有發生過,但是,用python進行解碼的時候,卻會出現錯誤。

我們執行上面的測試指令碼,可以看到出現這樣的情況:

    <li id="J_menuHistory" data-page="J_pageHistory">
                                    <a><i class="icon-history"></i>播放歷史     \0xe5 </a>
  • 1
  • 2

當然,這段程式碼是我隨手寫的一個例子,這裡,可以注意看到這個0xe5,這是無法轉換出來的部分,這是不屬於編碼字符集中的部分。所以,在進行編碼轉換的時候,會報錯。

0x03 解決方法

  1. 修改字符集引數,一般這種情況出現得較多是在國標碼(GBK)和utf8之間選擇出現了問題。
  2. 出現異常報錯是由於設定了decode()方法的第二個引數errors為嚴格(strict)形式造成的,因為預設就是這個引數,將其更改為ignore等即可。例如:
line.decode("utf8","ignore")