看透「0」、「1」邏輯,輕鬆解決Python中文亂碼
文:朱元祿(@數據分析-jacky)
Python中關於「中文亂碼」的問題,現規整如下,並統一回答
同學問:
jacky:我在爬取XX網站信息的時候,中文怎麼總是顯示的亂碼?jacky:UTF-8與GBK到底是個啥?jacky:我用的是Mac系統,網上說Python3中默認的編碼是UTF-8,可我顯示中文時怎麼還是亂碼?
(一)邏輯導圖
- Python中為什麼會出現亂碼?
- 解碼與編碼方式不一致
- 解碼與編碼具體方式有哪些?
- 實質是什麼?
- Python亂碼問題總結
(二)基礎鋪墊
1.計算機的底層邏輯
(第1層)
生活、交易、娛樂、科學研究,都離不開計算機(廣義)。
無所不能的計算機是怎樣實現其功能的?
(第2層)
通過計算機語言編碼實現的(Python就是其中之一)。
那麼語言編碼又是怎樣構成的?
(第3層)
計算機語言是由字母,字元和數字組合而成的,不同的排列組合,構成了不同的語言要素,其排列組合的規則就是編碼語言的語法。
接下來,我們要探討,這些規則是如何制定的?
(第4層)
通過0和1的不同組合,若干個0和1,若干種組合,我們制定了編碼語言的不同規則為什麼只是0和1的組合?
(第5層)
這裡的0和1,也只是輔助我們標記計算機規則的標記的是什麼?
(第6層)
標記電路最底層的兩種狀態:通電和不通電
(第7層)
計算機底層就是電路,現階段,人類處理電路可能的辦法只能是讓它通電,或不通電。
人類是多麼的偉大僅用0和1,就構建了我們現在這個機器智能的世界(水印:@數據分析-jacky)
2.字元編碼
計算機只能讀取二進位的「0」和「1」
ASCII
- 這個世界的規則就是誰發起,誰定規則。計算機是美國人發明的,在開發計算機的時候,美國人只考慮到了英文的兼容性,並沒有考慮包括中文在內的其他語言。
- 英語構成計算機最底層的元素就是:26個英語字母,加上特殊字元,加上數字。
(1)發明計算機時,字元編碼使用的是ascii碼,包括Python2默認的字元編碼就是ascii碼(Python3默認使用的是UTF-8,詳見下文);
(2)ascii碼為1位元組(8位)
- 8位二進位(例如:01010101)有多少種排列組合? =256種可能
- 對於英文來說,8位二進位足夠用了,所有python2還默認ascii碼也不足為奇。
Unicode(萬國碼)
- 全球化和科技共享,讓計算機的開發者認識到,要開發一種各國語言都能兼容的編碼,就有了unicode,也叫萬國碼。
(1)unicode 包含各國所有的語言文件和符號,對於中文來說,8位已經不夠用了,unicode規定:一個中文漢字最少用3個位元組來表示。
- 一個位元組是8位,1byte=8bit=01010101,一個漢字最少有2的24次方種組合
(2)Python中可以用bin函數將十進位轉化為二進位
bin(82)0b1010010 #b表示的R是二進位n
(3)萬國碼的弊端
- 占內存和硬碟
- 用英文字母R舉例:如何用ascii碼錶示為』0b1010010』,如何用萬國碼錶示為『000000000b1010010』,因為萬國碼,最少是2個位元組,與ascii相比,萬國碼白白浪費了1個位元組的空間。
- 針對unicode的弊端,如今的開發者,又對unicode進行了精簡,開發了UTF-8編碼
(4)特別說明(讀完下文在回來看,就好理解了)
- Unicode是Python的內部編碼,也是編碼和解碼的中間編碼。
UTF-8編碼
- UTF-8編碼是對unicode 的一個再加工
- 對unicode 的編碼進行了劃分和整理,用8位的就劃分為用8位的,不額外在用空間
- 規則:
- 英文:8位
- 歐洲:16位
- 中文:24位
- 特別說明:在Unicode編碼方式下,才存在 utf-8,utf-16,utf-32的編碼方式,這句話對於解釋下文的解碼與編碼特別重要
GBK編碼
(三)編碼與解碼
1、基礎內容
編碼:將字元轉化為二進位位元組的過程
解碼:將二進位位元組轉化為字元的過程
2、解碼和編碼的實現方法
(1) 基本邏輯
字元串在Python內部的表示是Unicode編碼。
因此在做編碼轉換時,通常需要以Unicode作為中間編碼,即先將其他編碼的字元串解碼(decode)成Unicode,再從Unicode編碼(encode)成另一種編碼。
(2) encode與decode
decode的作用是將其他編碼的字元串轉換成Unicode編碼,如str1.decode(『gbk』),表示將gbk編碼的字元串str1轉換成Unicode編碼;
encode的作用是將Unicode編碼轉換成其他編碼的字元串,如str2.encode(『UTF-8』),表示將Unicode編碼的字元串str2轉換成UTF-8編碼
因此,使用Python轉碼的時候一定要先搞明白,字元串str是什麼編碼,然後decode成Unicode,然後再encode成其他編碼。
特別注意:
- 如果一個字元串已經是unicode了,再進行解碼則將出錯,因此通常要對其編碼方式是否為unicode進行判斷:
- 用非unicode編碼形式的string來encode也會報錯
(3)支持字元串類型的兩種數據模型
python編碼有兩種數據模型來支持字元串類型 :
- 一種是str ;
- 一種是unicode
(四)解決Python亂碼的思路
- 亂碼?
- Unicode中轉碼
- 我們需要的編碼方式
代碼的實現方式:
decode()->unicode->encode轉化為需要的格式n
實戰案例:
content為從文件中讀取的gbk編碼的內容,我們通過以上方法輸出該內容。
content.decode(gbk).encode(utf-8)n
- decode方法將content內容轉為unicode格式
- encode方法將unicode格式的數據轉化為自己所需要的編碼方式。
(五)數據科學領域需注意的問題
作為數據分析(挖掘)師,python與資料庫的關聯是最常見的,我們用python連接資料庫後,將數據寫到資料庫里的中文有時會是亂碼
解決辦法是在python文件中加上這樣幾句話:
conn.set_character_set(utf8)ncur.execute(SET CHARACTER SET utf8)ncur.execute(SET character_set_connection=utf8)n
- conn是資料庫的connection,cur是connection的游標cursor
推薦閱讀:
※用 cx_Freeze 將 Python 腳本編譯為 Windows exe 實戰
※為什麼優礦的策略跑起來都很成功,是因為哪些因素沒有考慮到?
※[21] Python函數(二)
※解構國內首個函數計算(從概念、入門再到實戰)
TAG:Python |