python基礎===解決python3 UnicodeEncodeError: 'gbk' codec can't encode character '\xXX' in position XX(轉載

本文轉自:解決python3 UnicodeEncodeError: 'gbk' codec can't encode character '\xXX' in position XXhtml

 

從網上抓了一些字節流,想打印出來結果發生了一下錯誤:python

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

代碼app

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

錯誤信息讓人很困惑,爲何用的是'utf-8'解碼,錯誤信息卻提示'gbk'錯誤呢?函數

 

不只如此,從百度首頁的html中發現如下代碼:post

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

這說明網頁的確用的是utf-8,爲何會出現Error呢?測試

 

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

1.字符就是unicode字符,字符串就是unicode字符數組google

若是用如下代碼測試,編碼

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 繁體中文

這是我獲取知乎的頁面:

import requests
import re
import sys
import io

sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030') #改變標準輸出的默認編碼
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'
    }
r = requests.get("https://www.zhihu.com/explore",headers = headers)

print(r.status_code)
print(r.text)
相關文章
相關標籤/搜索