標籤:

看透「0」、「1」邏輯,輕鬆解決Python中文亂碼

文:朱元祿(@數據分析-jacky)

Python中關於「中文亂碼」的問題,現規整如下,並統一回答

同學問:

jacky:我在爬取XX網站信息的時候,中文怎麼總是顯示的亂碼?

jacky:UTF-8與GBK到底是個啥?

jacky:我用的是Mac系統,網上說Python3中默認的編碼是UTF-8,可我顯示中文時怎麼還是亂碼?

(一)邏輯導圖

  1. Python中為什麼會出現亂碼?
  2. 解碼與編碼方式不一致
  3. 解碼與編碼具體方式有哪些?
  4. 實質是什麼?
  5. 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亂碼的思路

  1. 亂碼?
  2. Unicode中轉碼
  3. 我們需要的編碼方式

代碼的實現方式:

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 |