Python爬蟲技術--基礎篇--內建模組base64
1.base64
Base64是一種用64個字元來表示任意二進位制資料的方法。
用記事本開啟exe
、jpg
、pdf
這些檔案時,我們都會看到一大堆亂碼,因為二進位制檔案包含很多無法顯示和列印的字元,所以,如果要讓記事本這樣的文字處理軟體能處理二進位制資料,就需要一個二進位制到字串的轉換方法。Base64是一種最常見的二進位制編碼方法。
Base64的原理很簡單,首先,準備一個包含64個字元的陣列:
['A', 'B', 'C', ... 'a', 'b', 'c', ... '0', '1', ... '+', '/']
然後,對二進位制資料進行處理,每3個位元組一組,一共是3x8=24
bit,劃為4組,每組正好6個bit:
這樣我們得到4個數字作為索引,然後查表,獲得相應的4個字元,就是編碼後的字串。
所以,Base64編碼會把3位元組的二進位制資料編碼為4位元組的文字資料,長度增加33%,好處是編碼後的文字資料可以在郵件正文、網頁等直接顯示。
如果要編碼的二進位制資料不是3的倍數,最後會剩下1個或2個位元組怎麼辦?Base64用\x00
位元組在末尾補足後,再在編碼的末尾加上1個或2個=
號,表示補了多少位元組,解碼的時候,會自動去掉。
Python內建的base64
可以直接進行base64的編解碼:
>>> import base64
>>> base64.b64encode(b'binary\x00string')
b'YmluYXJ5AHN0cmluZw=='
>>> base64.b64decode(b'YmluYXJ5AHN0cmluZw==')
b'binary\x00string'
由於標準的Base64編碼後可能出現字元+
和/
,在URL中就不能直接作為引數,所以又有一種"url safe"的base64編碼,其實就是把字元+
和/
分別變成-
和_
:
>>> base64.b64encode(b'i\xb7\x1d\xfb\xef\xff')
b'abcd++//'
>>> base64.urlsafe_b64encode(b'i\xb7\x1d\xfb\xef\xff')
b'abcd--__'
>>> base64.urlsafe_b64decode('abcd--__')
b'i\xb7\x1d\xfb\xef\xff'
還可以自己定義64個字元的排列順序,這樣就可以自定義Base64編碼,不過,通常情況下完全沒有必要。
Base64是一種通過查表的編碼方法,不能用於加密,即使使用自定義的編碼表也不行。
Base64適用於小段內容的編碼,比如數字證書籤名、Cookie的內容等。
由於=
字元也可能出現在Base64編碼中,但=
用在URL、Cookie裡面會造成歧義,所以,很多Base64編碼後會把=
去掉:
# 標準Base64:
'abcd' -> 'YWJjZA=='
# 自動去掉=:
'abcd' -> 'YWJjZA'
去掉=
後怎麼解碼呢?因為Base64是把3個位元組變為4個位元組,所以,Base64編碼的長度永遠是4的倍數,因此,需要加上=
把Base64字串的長度變為4的倍數,就可以正常解碼了。
小結
Base64是一種任意二進位制到文字字串的編碼方法,常用於在URL、Cookie、網頁中傳輸少量二進位制資料。
2.struct
準確地講,Python沒有專門處理位元組的資料型別。但由於b'str'
可以表示位元組,所以,位元組陣列=二進位制str。而在C語言中,我們可以很方便地用struct、union來處理位元組,以及位元組和int,float的轉換。
在Python中,比方說要把一個32位無符號整數變成位元組,也就是4個長度的bytes
,你得配合位運算子這麼寫:
>>> n = 10240099
>>> b1 = (n & 0xff000000) >> 24
>>> b2 = (n & 0xff0000) >> 16
>>> b3 = (n & 0xff00) >> 8
>>> b4 = n & 0xff
>>> bs = bytes([b1, b2, b3, b4])
>>> bs
b'\x00\x9c@c'
非常麻煩。如果換成浮點數就無能為力了。
好在Python提供了一個struct
模組來解決bytes
和其他二進位制資料型別的轉換。
struct
的pack
函式把任意資料型別變成bytes
:
>>> import struct
>>> struct.pack('>I', 10240099)
b'\x00\x9c@c'
pack
的第一個引數是處理指令,'>I'
的意思是:
>
表示位元組順序是big-endian,也就是網路序,I
表示4位元組無符號整數。
後面的引數個數要和處理指令一致。
unpack
把bytes
變成相應的資料型別:
>>> struct.unpack('>IH', b'\xf0\xf0\xf0\xf0\x80\x80')
(4042322160, 32896)
根據>IH
的說明,後面的bytes
依次變為I
:4位元組無符號整數和H
:2位元組無符號整數。
所以,儘管Python不適合編寫底層操作位元組流的程式碼,但在對效能要求不高的地方,利用struct
就方便多了。
struct
模組定義的資料型別可以參考Python官方文件:
https://docs.python.org/3/library/struct.html#format-characters
Windows的點陣圖檔案(.bmp)是一種非常簡單的檔案格式,我們來用struct
分析一下。
首先找一個bmp檔案,沒有的話用“畫圖”畫一個。
讀入前30個位元組來分析:
>>> s = b'\x42\x4d\x38\x8c\x0a\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00\x00\x00\x80\x02\x00\x00\x68\x01\x00\x00\x01\x00\x18\x00'
BMP格式採用小端方式儲存資料,檔案頭的結構按順序如下:
兩個位元組:'BM'
表示Windows點陣圖,'BA'
表示OS/2點陣圖; 一個4位元組整數:表示點陣圖大小; 一個4位元組整數:保留位,始終為0; 一個4位元組整數:實際影象的偏移量; 一個4位元組整數:Header的位元組數; 一個4位元組整數:影象寬度; 一個4位元組整數:影象高度; 一個2位元組整數:始終為1; 一個2位元組整數:顏色數。
所以,組合起來用unpack
讀取:
>>> struct.unpack('<ccIIIIIIHH', s)
(b'B', b'M', 691256, 0, 54, 40, 640, 360, 1, 24)
結果顯示,b'B'
、b'M'
說明是Windows點陣圖,點陣圖大小為640x360,顏色數為24。