Python爬蟲基礎(chǔ) | 字符串和編碼

python字符串編碼的問題在爬蟲過程中無論是輸出到文件中還是輸出到DB數(shù)據(jù)庫(kù)中感覺是始終繞不過去的一道坎浸踩,所以趁這次碰到的問題 來做一個(gè)學(xué)習(xí)記錄

什么是Unicode
Unicode是計(jì)算機(jī)可以支持這個(gè)星球上多種語言的密碼武器。在Unicode之前,用的都是ASCII滩援。ASCII碼非常簡(jiǎn)單炉擅,每個(gè)英文字符都是以7位二進(jìn)制數(shù)的方式存貯在計(jì)算機(jī)內(nèi),其范圍是32~126清女。當(dāng)用戶在文件中鍵入一個(gè)大寫字符A時(shí)钱烟,計(jì)算機(jī)會(huì)把A的ASCII碼值65寫入磁盤,然后當(dāng)計(jì)算機(jī)讀取該文件時(shí)嫡丙,它首先會(huì)把65轉(zhuǎn)化成字符A然后顯示在屏幕上拴袭。
ASCII編碼的文件小巧易讀。一個(gè)程序只需簡(jiǎn)單地把文件的每個(gè)字節(jié)讀出來曙博,把對(duì)應(yīng)的數(shù)字轉(zhuǎn)換成字符顯示出來就可以了拥刻。但是ASCII編碼也有其局限性,就算后來擴(kuò)展到用8位二進(jìn)制的方式來存貯父泳,這個(gè)對(duì)于需要成千上萬的字符的非歐洲語系的語言來說仍然太少.
例如:處理中文顯然一個(gè)字節(jié)是不夠的般哼,至少需要兩個(gè)字節(jié),而且還不能和ASCII編碼沖突,這樣就使中國(guó)制定了GB2312編碼惠窄,全世界有上百種語言蒸眠,日本把日文編到Shift_JIS里,韓國(guó)把韓文編到Euc-kr里杆融,各國(guó)有各國(guó)的標(biāo)準(zhǔn)楞卡,就會(huì)不可避免地出現(xiàn)沖突,結(jié)果就是擒贸,在多語言混合的文本中臀晃,顯示出來會(huì)有亂碼
Unicode這個(gè)時(shí)候就應(yīng)運(yùn)而生介劫,通過使用一個(gè)或多個(gè)字節(jié)來表示一個(gè)字符的方法來突破ASCII的限制徽惋。在這樣的機(jī)制下,Unicode可以表示超過90000個(gè)字符座韵。
新的問題又出現(xiàn)了:如果統(tǒng)一成Unicode編碼险绘,亂碼問題從此消失了踢京。但是,如果你寫的文本基本上全部是英文的話宦棺,用Unicode編碼比ASCII編碼需要多一倍的存儲(chǔ)空間瓣距,在存儲(chǔ)和傳輸上就十分不劃算。
所以代咸,本著節(jié)約的精神蹈丸,又出現(xiàn)了把Unicode編碼轉(zhuǎn)化為“可變長(zhǎng)編碼”UTF-8編碼。UTF-8編碼把一個(gè)Unicode字符根據(jù)不同的數(shù)字大小編碼成1-6個(gè)字節(jié)呐芥,常用的英文字母被編碼成1個(gè)字節(jié)逻杖,漢字通常是3個(gè)字節(jié),只有很生僻的字符才會(huì)被編碼成4-6個(gè)字節(jié)思瘟。如果你要傳輸?shù)奈谋景罅坑⑽淖址┌伲?code>UTF-8編碼就能節(jié)省空間。

總結(jié)一下現(xiàn)在計(jì)算機(jī)系統(tǒng)通用的字符編碼工作方式:

在計(jì)算機(jī)內(nèi)存中滨攻,統(tǒng)一使用Unicode編碼够话,當(dāng)需要保存到硬盤或者需要傳輸?shù)臅r(shí)候,就轉(zhuǎn)換為UTF-8編碼光绕。

在 Python 中 Unicode 被視為是一種中間碼女嘲,如果要在不同的編碼間進(jìn)行轉(zhuǎn)化,通常是先將字符串解碼(decode)成 Unicode 編碼奇钞,再?gòu)?Unicode 編碼(encode)成另一種編碼:

  • decode: 的作用是將其他編碼的字符串轉(zhuǎn)換成 Unicode 編碼澡为,例如: name.decode(“GB2312”),表示將 GB2312 編碼的字符串 name 轉(zhuǎn)換成 Unicode 編碼
  • encode: 的作用是將 Unicode 編碼轉(zhuǎn)換成其他編碼的字符串例如景埃,例如: name.encode(”GB2312“)媒至,表示 Unicode 編碼的字符串 name 轉(zhuǎn)換成 GB2312 編碼

我們會(huì)在很多 Python 的源碼文件的頭部看到如下的聲明:

# coding:utf-8

這表示聲明源代碼中的文本編碼為UTF-8,也就是告訴 Python 解釋器將文件中的文本視為 UTF-8 編碼的字符串谷徙,因此聲明的編碼應(yīng)該與文件的編碼保持一致拒啰。在代碼中我們通常會(huì)處理一些其他來源的文本,比如網(wǎng)絡(luò)完慧,它們的編碼不一定也是 UTF-8 的谋旦,因此就要進(jìn)行編碼轉(zhuǎn)換。

Python 試圖在字節(jié)串和字符串之間以不為人所察覺的方式進(jìn)行轉(zhuǎn)化屈尼。
在不同的轉(zhuǎn)換中册着,在條件允許的情況下,Python 會(huì)試圖在字節(jié)串unicode 字符串直接進(jìn)行轉(zhuǎn)換脾歧。例如將字節(jié)串unicode 字節(jié)串連接到一起時(shí)甲捏。但是不使用 encoding 就在不同類型之間進(jìn)行轉(zhuǎn)換是沒有意義的。所以 Python 依賴一個(gè) 默認(rèn)編碼鞭执,該編碼由 sys.setdefaultencoding() 指定司顿。在大多數(shù)平臺(tái)上芒粹,默認(rèn)的是 ASCII編碼。但對(duì)于所有轉(zhuǎn)換大溜,使用這種編碼幾乎都是錯(cuò)誤的化漆。如果不手動(dòng)指定編碼就調(diào)用 str()unicode() ,或是函數(shù)以字符串作為參數(shù)钦奋,但傳遞的是其他類型的參數(shù)時(shí)座云,都會(huì)使用這個(gè)默認(rèn)編碼。這就是很多時(shí)候出現(xiàn) UnicodeEncodeError 和 UnicodeDecodeError 錯(cuò)誤的原因锨苏,也就是字符串對(duì)象互相轉(zhuǎn)化時(shí)沒有指定字符編碼疙教。

例如,如果對(duì) unicodestr 類型通過 + 拼接時(shí)伞租,輸出結(jié)果是 unicode 類型,相當(dāng)于先將 str 類型的字符串通過 decode() 方法解碼成unicode再拼接限佩。此時(shí)如果解碼時(shí)沒有明確指明編碼類型葵诈,可能會(huì)出現(xiàn)錯(cuò)誤。

解決這個(gè)問題的一個(gè)辦法是祟同,代碼開頭就調(diào)用 sys.setdefaultencoding()將默認(rèn)的編碼設(shè)置為真正會(huì)用到的編碼作喘。但這樣僅僅是將問題隱藏起來,雖然這樣剛開始能解決一些文本處理問題晕城。但缺乏實(shí)際可行性泞坦,因?yàn)樵S多應(yīng)用,特別是網(wǎng)絡(luò)應(yīng)用砖顷,在不同的地方會(huì)使用不同的文本編碼贰锁。

下面是一些處理 Python 中字符編碼的建議:

  • 所有文本字符串都應(yīng)該是 unicode 類型,而不是str 類型滤蝠。
  • 若要將字節(jié)串解碼成字符串豌熄,需要使用正確的解碼,即 var.decode(encoding)物咳,如: var.decode(‘utf-8’)锣险;將文本字符串編碼成字節(jié),使用 var.encode(encoding)览闰。
  • 永遠(yuǎn)不要對(duì) unicode 字符串使用 str()芯肤,也不要在不指定編碼的情況下就對(duì)字節(jié)串使用 unicode()
  • 當(dāng)應(yīng)用從外部讀取數(shù)據(jù)時(shí)压鉴,應(yīng)將其視為字節(jié)串崖咨,即 str 類型的,接著調(diào)用.decode() 將其解釋成文本晴弃。同樣掩幢,在將文本發(fā)送到外部時(shí)逊拍,總是對(duì)文本調(diào)用 .encode()
  • 對(duì)標(biāo)準(zhǔn)流進(jìn)行操作時(shí)际邻,可以改變環(huán)境變量PYTHONIOENCODING 的值來設(shè)置標(biāo)準(zhǔn)流的默認(rèn)編碼芯丧, sys.stdin.encodingsys.stdout.encoding 的值為期望的編碼。
參考資料

廖雪峰的官方網(wǎng)站-字符串和編碼
Unicode HOWTO
http://www.tuicool.com/articles/2MVRVv7
https://gist.github.com/x7hub/178c87f323fbad57ff91
http://python.jobbole.com/86578/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末世曾,一起剝皮案震驚了整個(gè)濱河市缨恒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌轮听,老刑警劉巖骗露,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異血巍,居然都是意外死亡萧锉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門述寡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來柿隙,“玉大人,你說我怎么就攤上這事鲫凶≠餮拢” “怎么了?”我有些...
    開封第一講書人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵螟炫,是天一觀的道長(zhǎng)波附。 經(jīng)常有香客問我,道長(zhǎng)昼钻,這世上最難降的妖魔是什么掸屡? 我笑而不...
    開封第一講書人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮换吧,結(jié)果婚禮上折晦,老公的妹妹穿的比我還像新娘。我一直安慰自己沾瓦,他們只是感情好满着,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著贯莺,像睡著了一般风喇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上缕探,一...
    開封第一講書人閱讀 52,736評(píng)論 1 312
  • 那天魂莫,我揣著相機(jī)與錄音,去河邊找鬼爹耗。 笑死耙考,一個(gè)胖子當(dāng)著我的面吹牛谜喊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播倦始,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼斗遏,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了鞋邑?” 一聲冷哼從身側(cè)響起诵次,我...
    開封第一講書人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎枚碗,沒想到半個(gè)月后逾一,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肮雨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年遵堵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怨规。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鄙早,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出椅亚,到底是詐尸還是另有隱情,我是刑警寧澤舱污,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布呀舔,位于F島的核電站,受9級(jí)特大地震影響扩灯,放射性物質(zhì)發(fā)生泄漏媚赖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一珠插、第九天 我趴在偏房一處隱蔽的房頂上張望惧磺。 院中可真熱鬧,春花似錦捻撑、人聲如沸磨隘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽番捂。三九已至,卻和暖如春江解,著一層夾襖步出監(jiān)牢的瞬間设预,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工犁河, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鳖枕,地道東北人魄梯。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像宾符,于是被迫代替她去往敵國(guó)和親酿秸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 字符集和編碼簡(jiǎn)介 在編程中常澄可以見到各種字符集和編碼允扇,包括ASCII,MBCS,Unicode等字符集。確切的說...
    蘭山小亭閱讀 8,514評(píng)論 0 13
  • 可以看我的博客 lmwen.top 或者訂閱我的公眾號(hào) 簡(jiǎn)介有稍微接觸python的人就會(huì)知道则奥,python中...
    ayuLiao閱讀 3,126評(píng)論 1 5
  • 在學(xué)習(xí)python2的時(shí)候,字符串和編碼可以說是最讓人困惑的知識(shí)點(diǎn),假如知其然而不知其所以然,則在后續(xù)的寫代碼和學(xué)...
    虞大膽的嘰嘰喳喳閱讀 1,763評(píng)論 2 21
  • 我一直認(rèn)為考润,對(duì)過去的不斷懷念是因?yàn)楝F(xiàn)在的無所事事,而現(xiàn)在的我正處于這種狀態(tài)读处。家庭一般糊治、長(zhǎng)的一般、學(xué)習(xí)一般罚舱、就連每天...
    Sevenine玖柒閱讀 180評(píng)論 0 0
  • 每日推薦: 每日一歌――張懸《喜歡》 每日一詩――王勃《別薛華》 送送多窮路井辜,遑遑獨(dú)問津。 悲涼千里道管闷,凄斷百年身...
    薩拉芯雪閱讀 228評(píng)論 0 1