錯(cuò)誤信息:UnicodeEncodeError: 'ascii' codec can't encode characters in position 21-22: ordinal not in range(128)。ascii碼不能對(duì)位于21-22的字符進(jìn)行編碼,為什么呢,他的編碼不在128的范圍類。問題:ASCII碼是什么?我們第一期說過,在計(jì)算機(jī)里面,是用數(shù)字0和1來表示信息的。用0和1表示數(shù)字的方式,叫二進(jìn)制。可是怎么表示文字呢?簡(jiǎn)單,把文字轉(zhuǎn)換成數(shù)字就可以了。轉(zhuǎn)換嘛,其實(shí)制定一套編碼指定哪個(gè)數(shù)字代表哪個(gè)字符。一幫人糾結(jié)來糾結(jié)去,后來選擇了0—127,代表了26個(gè)小寫字母、26個(gè)大寫字母、10個(gè)數(shù)字、32個(gè)符號(hào)、33個(gè)句柄和一個(gè)空格總共128個(gè)字符,這就是ASCII碼。現(xiàn)在知道錯(cuò)誤信息里的128怎么來的了吧。因?yàn)槭敲绹?guó)人發(fā)明的,所以并沒有考慮中文,甚至他們的老兄弟英國(guó)的英鎊符號(hào)都沒有考慮進(jìn)去。所以,我們的中文字符“胡歌”,要用ascii去解碼的時(shí)候,就會(huì)出錯(cuò)了。怎么辦呢?活人當(dāng)然不會(huì)被尿憋死,既然別人老美可以有自己的編碼,我們就不能也設(shè)定一個(gè)么。于是,中國(guó)的編碼GB2312誕生。那么問題來了,有沒有一套編碼,包含各個(gè)國(guó)家的字符呢?當(dāng)然有,Unicode!看Uni這個(gè)詞根,就知道他要搞大事情。然而這套編碼發(fā)明出來后大家并不太買賬,為什么呢,因?yàn)樗嫶蟆O胂階SCII碼,只有1到127,最大的127用二進(jìn)制表示是1111111,也就是說最少7位就能表示一個(gè)字符。想想U(xiǎn)nicode要成萬用碼,那長(zhǎng)度,真是我的天。為了克服Unicode的缺陷,又出來了UTF-8編碼,這套編碼與之前不同之處在于UTF8的編碼是變長(zhǎng)的。之前的比如ASCII碼,表示1是用0000001,表示127是用1111111,都是7位,但是UTF-8不同,他表示小的數(shù)字用的位數(shù)就少,表示大的數(shù)字用的位數(shù)就大。于是設(shè)計(jì)者就將常用的字符對(duì)應(yīng)比較小的數(shù)字,很少用的字符對(duì)應(yīng)比較大的數(shù)字,也就是大部分情況下,他占的資源還是挺少的,這樣就兼顧了通用和效率。所以,只要將漢字“胡歌”表示成UTF-8就可以了。有同學(xué)表示不服:我直接搜索胡歌都是可以的,而且瀏覽器上顯示的也是漢字。為什么python就不可以,真是弱雞啊。我說這位同學(xué)你這是圖樣圖森破啊。看好了:
看實(shí)際上漢字變成了什么。那么這個(gè)%E8%83%A1%E6%AD%8C是什么呢?
是不是就是胡歌的UTF-8編碼,只不過用了十六進(jìn)制表示。好了,那怎么改?用我剛剛輸入的"胡歌".encode("utf-8")?那是不行的,一來,發(fā)現(xiàn)輸出的b'/xe8/x83/xa1/xe6/xad/x8c'前面有個(gè)b沒,這是什么?二來,輸出結(jié)果出來是/x,而在網(wǎng)址中是百分號(hào)。我先說解決方案,再解釋上面說的這些。解決方案:parse.quote("胡歌")。其中parse也是來自于上期說到的urllib模塊,他出來的效果,就是%E8%83%A1%E6%AD%8C。再來解釋上面說到的幾個(gè)問題。首先是/x,其實(shí)就是表示十六進(jìn)制,沒什么其他的意思。第二是百分號(hào)%,這是一個(gè)規(guī)定,在網(wǎng)址里面,遇到特殊符號(hào)就用%加符號(hào)的ASCII碼的十六進(jìn)制,遇到中文其實(shí)比較凌亂,有的是百分號(hào)加UTF-8編碼,有的是加GB2312編碼,這里我們暫時(shí)都用UTF-8,遇到坑了之后以后再說。最后,稍復(fù)雜一些,這個(gè)b是什么鬼。我們說了,Python有五個(gè)基本數(shù)據(jù)類型。然而,我們經(jīng)常下載文件,或者保存文件,是說多少B,多少KB,多少M(fèi)B,多少GB,沒聽說過我們存了一個(gè)int,兩個(gè)str,三個(gè)float。所以,在網(wǎng)絡(luò)傳輸,磁盤存儲(chǔ)的時(shí)候,都要將這些轉(zhuǎn)成以字節(jié)bytes為單位的數(shù)據(jù)。1B=8bytes。Python對(duì)bytes類型的數(shù)據(jù)用帶b前綴的單引號(hào)或雙引號(hào)表示。要將字符串轉(zhuǎn)換成字節(jié),用encode();要將字節(jié)信息轉(zhuǎn)換成字符串,用decode()。
如果不選編碼,會(huì)默認(rèn)使用Unicode。好了,編碼的問題講完了,我們修改一下代碼,再運(yùn)行一下。
獲取到數(shù)據(jù)了吧,而且看最后,我們獲取到的數(shù)據(jù)是不是也是開頭有個(gè)b的,從網(wǎng)絡(luò)獲取的數(shù)據(jù)都是這樣,我們?cè)侔阉獯a一下,弄成字符串,方便以后處理:htmlstr = data.decode("utf-8", "ignore")ignore是為了防止一些莫名的解碼錯(cuò)誤,遇到了就忽視掉。好了,現(xiàn)在我們拿到數(shù)據(jù)了,下一步,就要從這些數(shù)據(jù)中找出圖片了。
歡迎關(guān)注我的微信公眾號(hào)獲取最新文章:

新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注