關於python3的編碼類型,到底是怎么編碼的,一直使我比較疑惑,在看了網上很多帖子之后,經過自己嘗試與實驗,將自己的總結寫在下面,一是當做一次筆記,二是希望網友們能指正。僅供參考,歡迎指正,謝謝!!!
一、編碼類型
首先,我們需要明白的是計算機只能識別0、1這種二進制的信息,再說字節,字節是計算機的最小處理單元。一個字節占 8 位,也就是說在計算機中最小可以處理 8 位的二進制數。同時,在計算機上存儲的數據也是以字節為單位的信息,在讀取計算機上的信息時就是讀取的二進制的這些0、1組成的數字信息。
關於各種編碼類型,常用的有 Ascii、UTF-8、GBK、GB2312以及Unicode 。我們從Ascii理解他們是怎么來的。
因為計算機只能識別二進制數,那么如何使計算機能夠表示字母以及數字等形式呢?於是想到了建立一個標准碼來翻譯成計算機能識別的二進制數,形成一一對應,那么輸入一個字符,那么就能計算機就可以轉變為二進制,從而理解。同時,計算機的最小處理單元是 8 位的二進制數,因此這個標准碼就占用了 8 位。那么就可以有2的8次方種0、1組合來表示常用的英文字符,然而標准的 ascii 沒有用滿這 8 位,只用了 7 位。之后又由於制表符、數學符號等里面並沒有,這張表在 128 個數的基礎上擴展到了 256 個,即 “擴展 ascii”。
在之后,256 個字符根本無法表示全人類的語言,於是進一步擴展到了 2 個字節,也是就是2的16次方,這也是中文為什么占兩個字符,而英文字符只需要占一個,也就產生了GBK等編碼方式,其實就是中文字與0、1排列組合的映射表使計算機能夠理解。
在之后由於世界各種的編碼方式不同,不利於統一交流,於是出現了Unicode、utf8等格式。
簡單理解就是為了使計算機處理英文字符,產生了ASCII碼;為了處理中文字符,產生了GB2312;為了處理各國字符,產生了Unicode;為了提高Unicode存儲和傳輸性能,產生了UTF-8,它是Unicode的一種實現形式。
同時,各種編碼方式都對應一張0、1組合的二進制表,以此保存信息,單位為字節。
二、python3的編碼
1.python3中文本字符串str和字節字符串是嚴格區分的
首先理解encode(encoding)與decode的定義:
編碼(encode):將Unicode字符串(中的代碼點)轉換特定字符編碼對應的字節串的過程和規則
解碼(decode):將特定字符編碼的字節串轉換為對應的Unicode字符串(中的代碼點)的過程和規則
其次,在python3中顯示的字符串是以unicode進行編碼的,要想轉變為其他編碼格式需要對其進行encode()編碼,下面請看示例:

由上圖看出:
(1)a是一個字符串,其編碼格式是unicode,類型為str字符串,但是將其進行編碼成utf8格式,會出現開頭為b的字節字符串,其類型為 bytes 故可以發現兩者是不同的。
(2)字符串str本身沒有decode這個方法,因為其本身就是unicode的
(3)將a先解碼在編碼就可以變為原來的字符串,說明,在python3中編碼必須經過unicode進行轉化
2.關於pthon3中對於文件的讀取寫入與儲存
2.1 首先定義一個“1.txt”,內容為"哈哈123abc“”,我們來看一下,python3是以什么方式讀取寫入文件的。在這里先說一下如何看txt的編碼格式以及如何修改txt文件的編碼格式,即打開txt 》 點擊做上方文件 》 點擊另存為 》會出現下方的圖 》可以根據需要選擇編碼也可以查看編碼類型
注:顯示的為當下的編碼類型

2.2 其次,我們來看一下讀入文件的編碼方式:
2.2.1在txt為utf8下:

由上圖可知;
(1)所謂亂碼本質上是系統(windows默認)編碼與所提供字符的編碼不一致導致的(windows默認ANSI),ansi在世界由地方不同而不同,在簡體中文Windows操作系統中,ANSI 編碼代表 GBK 編碼;在繁體中文Windows操作系統中,ANSI編碼代表Big5;在日文Windows操作系統中,ANSI 編碼代表 Shift_JIS 編碼,等等。
(2)本人系統是簡體中文Windows,在不明確以什么編碼方式打開下,會顯示出亂碼,且亂碼在明確以utf8下是一致的,在表明是gbk下是亂碼一致。故可知python3是以ANSI讀取存在系統的字節信息,然后內部自動解碼成unicode。之前說過python是區分字符unicode和字節字符(utf8\gbk等)的,在此並不是顯示的字節類型,而是字符串str,故encoding的作用是指示python以什么方式解碼所要讀取信息,使之成為unicode。
注:已有記事本文件(非空),轉碼 UTF-8,復制到pycharm中,在開始位置打印結果會出現\ufeff
2.2.2在txt為gbk(ANSI)下:

由上圖可知:
(1)在gbk格式下的txt文件,在不指明編碼方式下就可以正確讀取為字符串,印證了上述看法
(2)在指明為utf8下會報錯,但在上面未報錯,只是出現亂碼,總之不能正確解碼
2.3 最后,來看一下python保存文件的編碼格式(仍以txt為例)


由上圖可知:
(1)默認是以ANSI進行保存,在使用encoding()指明編碼方式下,會使用指示的方式
(2)說明在python3中,會自動將unicode編碼輸出,encoding的作用很大
2.4 來看一下pythons自己的 .py文件是什么格式
Python程序時會指定工程編碼和文件編碼為UTF-8,Python代碼被保存到磁盤時就會被轉換為UTF-8編碼對應的字節(encode過程)后寫入磁盤。
當執行Python代碼文件中的代碼時,Python解釋器在讀取Python代碼文件中的字節串之后,需要將其轉換為UNICODE字符串(decode過程)之后才執行后續操作。
如圖:

由此可知 .py文件是以utf8格式進行保存的,即unicode格式是python在使用時將其他格式解碼生成操作,最后輸出時,會自動按要求或者默認格式編碼。
三. 關於網頁爬取編碼 r.text 與 r.content
對requests獲取的原始數據,有三種獲取形式:
一個是r.content(萬能,但須解碼) 一個是r.text 一個是resp.json()
text -- 審查元素中的全部,類型 str (直接表示為unicode)
content -- 以b開頭的審查元素中的全部內容,類型 byte(含有編碼形式的,故有時需要先解碼才能正常顯示文本,圖片則不需要解碼)
json() -- 是針對json格式數據,可以直接生成字典進行數據提取
對於網頁數據的爬取,也是需要編碼格式的:
(1)

這是慕課上嵩老師所寫的一個小的獲取網頁的代碼,其中需要r.encoding 要正確的獲得。不過現在網頁很多都是utf8寫的,即使不使用encoding,一般也能正確獲取。
(2)關於 content 獲取二進制的形式,如果需要變為text 這種獲取的格式,可以使用 r.content.decode('utf-8')
總結:
(1)python以聲明的編碼方式讀取文件字節(默認系統gbk)之后自動解碼為unicode,顯示為字符串,故字符串無decode用法。但是若將字符串編碼為字節字符串(有編碼格式的)再變為原字符串則需先decode再encode
(2) windows系統下,無論是python還是其他默認保存與讀取為gbk格式,除非在保存時指定編碼方式,encoding=utf8
(3) 在python中,從網上獲取r.text類型為str(unicode)無decode,但是r.content是二進制形式(帶編碼類型)需先解碼才可以==text
(4)爬蟲中的嘗試編碼格式r.encoding = r.apparent_encoding 使得返回的內容解碼正確(命令要打正確)才能在python中變為unicode
上面如果有什么邏輯錯誤或者理解錯誤的地方,請大家指正,感謝!!!
參考文獻:
https://www.cnblogs.com/zhangqigao/p/6496172.html
https://www.cnblogs.com/laolv/p/7397429.html
https://blog.csdn.net/u014297175/article/details/40507523 # 二進制、字節、編碼的關系
http://www.runoob.com/python/att-string-encode.html #python encode的方法
https://www.cnblogs.com/geekard/archive/2012/10/04/python-string-endec.html
作者:在水之濱
鏈接:https://www.jianshu.com/p/74c75c2bebc0
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。