我本來不會Python,一邊學一邊試圖以最簡單方式來解釋編程和Python,讓各位理工男可以拿去教自己的女朋友。上期我們寫了讓數據到碗里來的代碼,然而并沒有運行,所有沒有進行測試運行的代碼,都是坑,天大的坑,現在,我們來填坑。我為什么沒運行呢?因為我知道會出錯!什么錯?請看:錯誤信息:UnicodeEncodeError: 'ascii' codec can't encode characters in position 21-22: ordinal not in range(128)。ascii碼不能對位于21-22的字符進行編碼,為什么呢,他的編碼不在128的范圍類。問題:ASCII碼是什么?我們第一期說過,在計算機里面,是用數字0和1來表示信息的。用0和1表示數字的方式,叫二進制??墒窃趺幢硎疚淖帜??簡單,把文字轉換成數字就可以了。轉換嘛,其實制定一套編碼指定哪個數字代表哪個字符。一幫人糾結來糾結去,后來選擇了0—127,代表了26個小寫字母、26個大寫字母、10個數字、32個符號、33個句柄和一個空格總共128個字符,這就是ASCII碼?,F在知道錯誤信息里的128怎么來的了吧。因為是美國人發明的,所以并沒有考慮中文,甚至他們的老兄弟英國的英鎊符號都沒有考慮進去。所以,我們的中文字符“胡歌”,要用ascii去解碼的時候,就會出錯了。怎么辦呢?活人當然不會被尿憋死,既然別人老美可以有自己的編碼,我們就不能也設定一個么。于是,中國的編碼GB2312誕生。那么問題來了,有沒有一套編碼,包含各個國家的字符呢?當然有,Unicode!看Uni這個詞根,就知道他要搞大事情。然而這套編碼發明出來后大家并不太買賬,為什么呢,因為他太龐大。想想ASCII碼,只有1到127,最大的127用二進制表示是1111111,也就是說最少7位就能表示一個字符。想想Unicode要成萬用碼,那長度,真是我的天。為了克服Unicode的缺陷,又出來了UTF-8編碼,這套編碼與之前不同之處在于UTF8的編碼是變長的。之前的比如ASCII碼,表示1是用0000001,表示127是用1111111,都是7位,但是UTF-8不同,他表示小的數字用的位數就少,表示大的數字用的位數就大。于是設計者就將常用的字符對應比較小的數字,很少用的字符對應比較大的數字,也就是大部分情況下,他占的資源還是挺少的,這樣就兼顧了通用和效率。所以,只要將漢字“胡歌”表示成UTF-8就可以了。有同學表示不服:我直接搜索胡歌都是可以的,而且瀏覽器上顯示的也是漢字。為什么python就不可以,真是弱雞啊。我說這位同學你這是圖樣圖森破啊??春昧耍?img src="http://s1.VeVb.com/20170206/0fjt1iyvfy039.gif" alt="">看實際上漢字變成了什么。那么這個%E8%83%A1%E6%AD%8C是什么呢?是不是就是胡歌的UTF-8編碼,只不過用了十六進制表示。好了,那怎么改?用我剛剛輸入的"胡歌".encode("utf-8")?那是不行的,一來,發現輸出的b'/xe8/x83/xa1/xe6/xad/x8c'前面有個b沒,這是什么?二來,輸出結果出來是/x,而在網址中是百分號。我先說解決方案,再解釋上面說的這些。解決方案:parse.quote("胡歌")。其中parse也是來自于上期說到的urllib模塊,他出來的效果,就是%E8%83%A1%E6%AD%8C。再來解釋上面說到的幾個問題。首先是/x,其實就是表示十六進制,沒什么其他的意思。第二是百分號%,這是一個規定,在網址里面,遇到特殊符號就用%加符號的ASCII碼的十六進制,遇到中文其實比較凌亂,有的是百分號加UTF-8編碼,有的是加GB2312編碼,這里我們暫時都用UTF-8,遇到坑了之后以后再說。最后,稍復雜一些,這個b是什么鬼。我們說了,Python有五個基本數據類型。然而,我們經常下載文件,或者保存文件,是說多少B,多少KB,多少MB,多少GB,沒聽說過我們存了一個int,兩個str,三個float。所以,在網絡傳輸,磁盤存儲的時候,都要將這些轉成以字節bytes為單位的數據。1B=8bytes。Python對bytes類型的數據用帶b前綴的單引號或雙引號表示。要將字符串轉換成字節,用encode();要將字節信息轉換成字符串,用decode()。如果不選編碼,會默認使用Unicode。好了,編碼的問題講完了,我們修改一下代碼,再運行一下。獲取到數據了吧,而且看最后,我們獲取到的數據是不是也是開頭有個b的,從網絡獲取的數據都是這樣,我們再把他解碼一下,弄成字符串,方便以后處理:htmlstr = data.decode("utf-8", "ignore")ignore是為了防止一些莫名的解碼錯誤,遇到了就忽視掉。