字符編碼:
? ? 一、字符編碼的歷史:
? ? ? ? # 紙帶打孔機 編程
? ? ? ? # 匯編語言+機器語言
? ? ? ? # C、lisp、Fortran -- Python C++ Java
? ? ? ? 基本點:計算機里所有數據存儲、計算,都是通過二進制處理。
? ? ? ? 二進制: 0b01100001
? ? ? ? 十進制: int(0b0110001) -> 97
? ? ? ? 字符: chr(97) -> 'a'
? ? ? ? ASCII表:美國標準信息交換碼,只能表示常用的字母、數字和普通符號, 0~127之間,一個字符 占 1 個字節(jié)。
? ? ? ? latin-1: 在ASCII基礎上擴展了127個,包含了西方文字,德文、法文...
? ? ? ? gb2312: 在ASCII基礎上進行擴展,可以表示簡體中文(gb2312->gbk->gb18030),一個漢字 2 個字節(jié)
? ? ? ? Big5 : 在ASCII基礎上進行擴展,表示繁體中文..
? ? ? ? shift-jis : 在ASCII基礎上進行擴展,日文..
? ? ? ? 幾乎每個國家都有自己的編碼表,導致文字交流不方便。
? ? ? ? 注意:如果輸出字符時,沒有對應的編碼表支持,就會出現"亂碼"。
? ? ? ? 為了解決編碼不一致的問題,國際標準組織制定了一套新的編碼 Unicode,給全世界每一個字符單獨指定了一個新的二進制方式。
? ? ? ? 但是Unicode有個缺點,每個字符占用 3~4個字節(jié),比較浪費空間。
? ? ? ? 于是在Unicode基礎上進行了升級更新: utf-8 編碼(可變長的Unicode),一個字母占1個字節(jié),一個漢字占3個字節(jié)。
? ? ? ? 所以utf-8現在是世界上最流行應用最廣泛的編碼,90%以上的網頁字符編碼 默認為 utf-8,所有的Linux終端編碼默認是utf-8
? ? ? ? 簡體中文Windows 終端默認編碼是 gbk,但是可以通過 chcp 65001 修改為 utf-8
? ? 二、Python中的字符編碼和類型對比:
? ? ? ? Python3 中:
? ? ? ? ? ? Unicode編碼字符串,是 str 類型
? ? ? ? ? ? 非Unicode編碼字符串,是 bytes 類型
? ? ? ? Python2 中(了解):
? ? ? ? ? ? Unicode編碼字符串,是 unicode 類型
? ? ? ? ? ? 非Unicode編碼字符串, 是 str 類型
? ? ? ? 編碼統(tǒng)一處理口訣:任何操作系統(tǒng)下的任何編程語言的任何編碼,都可以和Unicode互相轉換。
? ? ? ? ? ? utf8_str? --> gbk_str
? ? ? ? ? ? # 對 utf-8 字符串按自身編碼進行解碼,返回 Unicode字符串
? ? ? ? ? ? unicode_str = utf8_str.decode("utf-8")
? ? ? ? ? ? # 對 Unicode字符串 按指定編碼進行編碼,返回 編碼后的字符串
? ? ? ? ? ? gbk_str = unicode_str.encode("gbk")
? ? 三、Python爬蟲程序需要處理的編碼場景:
? ? ? ? 1. 發(fā)送請求,獲取網頁字符串(不同的網頁,字符串編碼可能不一樣,編碼統(tǒng)一)
? ? ? ? 2. 數據解析過程中,需要處理的字符串編碼(編碼統(tǒng)一)
? ? ? ? 3. 將字符串保存到文件、數據庫時(編碼統(tǒng)一)
? ? 四、在python解釋器 終端里創(chuàng)建字符串的編碼:
? ? ? ? Python3:Unicode編碼
? ? ? ? Python2:根據操作系統(tǒng),簡體中文Windows -gbk, Linux - utf-8
? ? ? ? ? ? iPython2里, 全部統(tǒng)一為 utf-8
? ? 五、在Python代碼文件里創(chuàng)建的字符串編碼:
? ? ? ? Python3:Unicode編碼
? ? ? ? Python2:根據操作系統(tǒng),簡體中文Windows - gbk, Linux - utf-8
? ? ? ? ? ? iPython2里, 全部統(tǒng)一為 utf-8
? ? 六:代碼文件頭部編碼聲明:
? ? ? ? Python3 的代碼文件的文字,按utf-8保存
? ? ? ? Python2 的代碼文件文字,默認按 ascii 保存,所以需要手動聲明按 utf-8 保存代碼文字
? ? ? ? # -*- coding:utf-8 -*-
? ? ? ? 表示python代碼文件里面文字按 utf-8 保存
? ? 七、網頁字符串編碼:
? ? ? ? /html/head/meta/charset 指定的當前網頁的編碼,通過requests模塊獲取的網頁字符串,就是該編碼的字符串。
? ? 八、將 Unicode字符串數據 保存到文件中方法:
? ? ? ? 1. 在保存Unicode字符串時,手動編碼轉換再寫入(這種方式不會觸發(fā)解釋器編碼默認轉換)
? ? ? ? ? ? Python3:
? ? ? ? ? ? ? ? unicode_str = "你好"
? ? ? ? ? ? ? ? with open("test.txt", "wb") as f:
? ? ? ? ? ? ? ? ? ? f.write(unicode_str.encode("utf-8"))
? ? ? ? ? ? Python2:
? ? ? ? ? ? ? ? unicode_str = u"你好"
? ? ? ? ? ? ? ? with open("test.txt", "wb") as f:
? ? ? ? ? ? ? ? ? ? f.write(unicode_str.encode("utf-8"))
? ? ? ? 2. 在保存Unicode字符串時,通過 open()方法的 encoding 參數指定編碼(這種方式不會觸發(fā)解釋器編碼默認轉換)
? ? ? ? ? ? Python3:
? ? ? ? ? ? ? ? unicode_str = "你好"
? ? ? ? ? ? ? ? with open("test.txt", "w", encoding="utf-8") as f:
? ? ? ? ? ? ? ? ? ? f.write(unicode_str)
? ? ? ? ? ? Python2:
? ? ? ? ? ? ? ? Python2的 open() 方法默認沒有encoding參數,但是可以通過 codecs 模塊支持。
? ? ? ? ? ? ? ? import codecs
? ? ? ? ? ? ? ? unicode_str = "你好"
? ? ? ? ? ? ? ? with codecs.open("test.txt", "w", encoding="utf-8") as f:
? ? ? ? ? ? ? ? ? ? f.write(unicode_str)
? ? ? ? 3. 直接保存Unicode字符串到文件中,如果 既沒有通過encode編碼,也沒有通過encoding參數指定編碼,則觸發(fā)解釋器編碼默認轉換。
? ? ? ? ? ? ? ? Python會按照默認的解釋器編碼進行轉碼處理,再寫入文件。
? ? ? ? ? ? Python3:可以直接寫入Unicode到本地文件,默認文件編碼為 utf-8,因為Python3的解釋器編碼是 utf-8
? ? ? ? ? ? ? ? unicode_str = "你好"
? ? ? ? ? ? ? ? with open("test.txt", "w") as f:
? ? ? ? ? ? ? ? ? ? f.write(unicode_str)
? ? ? ? ? ? Python2:可以直接寫入Unicode到本地文件,可能會報出 UnicodeEncodeError,因為Python2的解釋器編碼默認是 ascii
? ? ? ? ? ? ? ? ? ? 只能對普通英文字母、數字和字符進行編碼轉換,如果Unicode里有中文,則編碼失敗(因為 ascii 不支持處理中文)
? ? ? ? ? ? ? ? # 解決方案:將Python2的解釋器編碼修改為 utf-8,這樣就可以寫入任意的Unicode字符串
? ? ? ? ? ? ? ? import sys
? ? ? ? ? ? ? ? reload(sys)
? ? ? ? ? ? ? ? sys.setdefaultencoding("utf-8")
? ? ? ? ? ? ? ? unicode_str = u"你好"
? ? ? ? ? ? ? ? with open("test.txt", "w") as f:
? ? ? ? ? ? ? ? ? ? f.write(unicode_str)
? ? 九、文件編碼:
? ? ? ? 1. 當第一次寫入一個字符串到文件中時,該文件編碼等同于字符串編碼
? ? ? ? 2. 當第二次寫入的字符串編碼,和第一次寫入字符串編碼不一致時,文件編碼被會修改,會導致之前的數據全部變成亂碼。
? ? ? ? 記?。翰灰谕粋€文件中,寫入不同編碼的字符串。一定要做編碼統(tǒng)一。