python爬蟲字元問題 爬蟲裡面的字串編碼的坑

2021-10-21 06:40:50 字數 2623 閱讀 9562

初學python寫爬蟲程式,上手很快,但字串的編碼問題卻一直困擾著我,我相信每乙個學習爬蟲的人都有過和我一樣的困惑。一旦走上了程式設計之路,如果你不把編碼問題搞清楚,那麼它就像幽靈一般糾纏你整個職業生涯,所以,今天就談談python的字串編碼。

0.前言

大家都知道,我們的計算機只能處理數字,而計算機是美國人發明的。他們只有26個字母,所有乙個子集,255個字元肯定夠用了,也就是用ascii編碼。但中文不一樣,255個字元根本不夠用,必須要2個位元組才行。

對於漢字,中國有自己的一套編碼規則叫gb2312,那麼其他的國家,也會出一套自己的編碼規則。這樣就會有幾百種編碼方式,怎麼辦呢?

於是就有一套叫unicode萬國碼,它為每種語言中的每個字元設定了統一並且唯一的二進位制編碼,以滿足跨語言、跨平台進行文字轉換、處理的要求。

unicode採用的做法就是增加位元組數,英語要1個位元組,漢語要2個位元組,其他語言可能也要2個位元組。怎麼統一呢?於是全面都有兩個位元組來編碼乙個字元。這樣雖然解決了統一的問題,但是會帶來乙個開銷問題。

如果資料量很大的時候,明明英文只要乙個位元組,但因為用了unicode硬給我分配了2個位元組的空間,儲存開銷變大了,傳輸開銷也變大了。

於是utf-8出現了,它是一種可變的編碼方式,是一種正對unicode的編碼方式,也就是說如果你想轉為utf-8,你的字元必須是unicode格式。

1.字元與位元組

乙個字元不等價於乙個位元組,字元是人類能夠識別的符號,而這些符號要儲存到計算機的儲存中就需要用計算機能夠識別的位元組來表示。乙個字元往往有多種表示方法,不同的表示方法會使用不同的位元組數。這裡說的不同的表示方法就是指字元編碼。

字元編碼的作用是將人類可識別的字元轉換為機器可識別的位元組碼,以及反向過程。例如,unicode才是真正的字串,而用ascii、utf-8、gbk等字元編碼表示的是位元組串。

我們寫**是寫在檔案中,而字元是以位元組形式儲存在檔案中的,因此當我們在檔案中定義字串時被當作位元組串也是可以理解的。

但是,我們需要的是字串,而不是位元組串(我們寫**處理的是我們能想象的資料,也就是字串,應該不會有人想象位元組串吧)。

乙個優秀的程式語言,應該嚴格區分兩者的關係並提供巧妙的完美支援。python2在這方面就表現的很不友好。

直到08年,python創始人龜叔越來越覺得,python裡面的好多東西已發展的不像他的初衷那樣,開始變得臃腫、不簡潔、並且有些設計讓人摸不著頭腦,比如unicode與str型別,str與bytes型別的關係,這給很多python程式設計師造成了困擾。

於是來了個大變革,python3橫空出世,不相容python2,python3比python2做了非常多的改進,其中乙個就是終於把字串變成了unicode,檔案預設編碼變成了utf-8,這意味著,只要用python3,無論你的程式是以哪種編碼開發的,都可以在全球各國電腦上正常顯示,簡直太棒啦!

2.編碼與解碼

python官方文件中對unicode字串、位元組串與編碼之間的關係有這樣一段描述:

unicode字串是乙個**點序列,**點取值範圍為0到0x10ffff(對應十進位制為1114111)。這個**點序列在儲存(包括記憶體和物理磁碟)中需要被表示為一組位元組(0到255之間的值)。而將unicode字串轉換為位元組序列的規則稱為編碼。

這裡說的編碼不是指定字元編碼,而是指編碼的過程以及這個過程中所使用到的unicode字元的**點與位元組的對映規則。這個對映不必是簡單的一對一對映,因此編碼過程也不必處理每個可能的unicode字元,例如:

將unicode字串轉換為ascii編碼的規則很簡單——對於每個**點:如果**點數值<128,則每個位元組與**點的值相同

如果**點數值》=128,則unicode字元無法在此編碼中進行表示(這種情況下,python會引發乙個unicodeencodeerror異常)

將unicode字串轉換為utf-8編碼使用以下規則:如果**點數值<128,則由相應的位元組值表示(與unicode轉ascii位元組一樣)

如果**點數值》=128,則將其轉換為乙個2個位元組,3個位元組或4個位元組的序列,該序列的每個位元組都在128到255之間。

簡單總結一下

編碼(encode):將unicode字串(中的**點)轉換特定字元編碼對應的字串的過程和規則。

解碼(decode):將特定字元編碼的位元組串轉換為對應的unicode字串(中的**點)的過程和規則。

3.python源**檔案的執行過程

我們都知道,磁碟上的檔案都是以二進位制格式存放的,其中文字檔案都是以某種特定編碼的位元組形式存放的。

對於程式源**檔案的字元編碼是由編輯器指定的,比如我們使用pycharm來編寫python程式時會指定檔案編碼為utf-8,那麼python**被儲存到磁碟時就會被轉換為utf-8編碼對應的位元組(encode過程)後寫入磁碟。

當執行python**檔案中的**時,python直譯器在讀取python**檔案中的位元組串之後,需要將其轉換為unicode字串(decode過程)之後才執行後續操作。

檔案頭部宣告:頂部的:#--coding:utf-8—這個並不是告訴你,用utf-8編碼的,而是說如果**中有中文注釋,就需要此宣告,不然中文顯示不了。

4.總結

對於python**中避免遇到編碼問題,一點小建議:字元編碼宣告:在**開頭宣告編碼格式

使用codes的open函式處理文字檔案

盡可能使用unicode而不是str

盡可能使用python3。

python 刪除爬蟲裡無法識別的表情字元

def character a try 如果報錯,則獲取報錯的字串資訊 dk.write a dk.close except exception as error 處理字串,獲取報錯的內容 u str error split u error str u 1 split b re.sub u erro...

python爬蟲亂碼問題

使用爬蟲爬取網頁文字 所有中文文字全是亂碼,如圖 源網頁編碼和爬取下來後的編碼格式不一致。如源網頁為gbk編碼的位元組流,而我們抓取下後程式直接使用utf 8進行編碼並輸出到儲存檔案中,這必然會引起亂碼 即當源網頁編碼和抓取下來後程式直接使用處理編碼一致時,則不會出現亂碼 此時再進行統一的字元編碼也...

python爬蟲 非同步爬蟲

壞處 無法無限制的開啟多執行緒或者多程序。執行緒池 程序池 適當使用 使用非同步實現高效能的資料爬取操作 人多力量大 環境安裝 pip install aiohttp 使用該模組中的clientsession 2表示同時存在兩個協程 pool pool 2 urls for i in range 1...