一日一技:輕鬆排雷,爬蟲讓gzip炸彈變啞炮
攝影:產品經理
鵝肝醬和某種貝殼肉
在昨天的文章《 一日一技:反爬蟲的極致手段,幾行代碼直接炸了爬蟲服務器 》中,我講到了後端如何使用gzip返回極高壓縮率的文件,從而瞬間卡死爬蟲。
大家都知道我的公眾號風格, 兩頭 得罪 討好人 。昨天我幫了後端,今天我就幫幫爬蟲。作為爬蟲,如何避免踩中gzip炸彈?
最直接的方法,就是把你的爬蟲隱藏起來,因為gzip炸彈只能在發現了爬蟲以後使用,否則就會影響到正常用户。只要你的爬蟲讓網站無法發現,那麼自然就不會踩中炸彈。
如果你沒有把握隱藏爬蟲,那麼,請繼續往下看。
查看gzip炸彈的URL返回的Headers,你會發現如下圖所示的字段:
你只需要判斷 resp.headers
中,是否有一個名為 content-encoding
,值包含 gzip
或 deflate
的字段。如果沒有這個字段,或者值不含 gzip
、 deflate
那麼你就可以放心,它大概率不是炸彈。
值得一提的是,當你不讀取 resp.content
、 resp.text
的時候,Requests是不會擅自給你解壓縮的,如下圖所示。因此你可以放心查看Headers。:

那麼,如果你發現網站返回的內容確實是 gzip
壓縮後的內容了怎麼辦呢?這個時候,我們如何做到既不解壓縮,又能獲取到解壓以後的大小?
如果你本地檢查一個 .gz
文件,那麼你可以使用命令 gzip -l xxx.gz
來查看它的頭信息:

打印出來的數據中,第一個數字是壓縮後的大小,第二個數字是解壓以後的大小,第三個百分比是壓縮率。這些信息是儲存在壓縮文件的頭部信息中的,不用解壓就能獲取到。
那麼當我使用Requests的時候,如何獲得壓縮後的二進制數據,防止它擅自解壓縮?方法其實非常簡單:
import requests resp = requests.get(url, stream=True) print(resp.raw.read())
運行效果如下圖所示:

此時可以看到,這個大小是壓縮後的二進制數據的大小。現在,我們可以使用如下代碼,在不解壓的情況下,查詢到解壓縮後的文件大小:
import gzip import io import requests resp = requests.get(url, stream=True) decompressed = resp.raw.read() with gzip.open(io.BytesIO(decompressed), 'rb') as g: g.seek(0, 2) origin_size = g.tell() print(origin_size)
運行效果如下圖所示:

打印出來的數字轉成MB就是10MB,也就是我們昨天測試的解壓後的文件大小。
使用這個方法,我們就可以在不解壓的情況下,知道網站返回的gzip壓縮數據的實際大小。如果發現實際尺寸大得離譜,那就可以確定是gzip炸彈了,趕緊把它丟掉。
未聞 Code·知識星球開放啦!
一對一答疑爬蟲相關問題
職業生涯諮詢
面試經驗分享
每週直播分享
......
未聞 Code·知識星球期待與你相見~
一二線大廠在職員工
十多年碼齡的編程老鳥
國內外高校在讀學生
中小學剛剛入門的新人
在 “未聞 Code技術交流羣” 等你來!
入羣方式:添加微信“mekingname”,備註“粉絲羣”(謝絕廣吿黨,非誠勿擾!)
- 一日一技:用Python做遊戲有多簡單
- 一日一技:如何批量給PDF添加水印?
- 一日一技:拋掉JavaScript,用HTML和Python做網站
- 一個讓我感到 "細思極恐" 的開源項目!
- 一日一技:FastAPI 接口限流
- 5 分鐘,使用內網穿透快速實現遠程手機桌面!
- Python Delorean 優秀的時間格式智能轉換工具
- 寫在公眾號粉絲2w時
- 一日一技:協程與多進程的完美結合
- 一個 "喪心病狂" 的開源項目
- python中如何優雅的實現代碼與敏感信息分離?
- Pandas 多進程處理數據,速度快了不少!
- 爬蟲出海Step by Step(一)
- 一日一知:架構到底是什麼?
- Python識別花卉種類,並自動整理分類!
- 這幾個摸魚神器,你怎麼能不知道
- FoolNLTK — 簡單好用的中文NLP工具包
- 一日一知:國內爬蟲開發人員的未來
- 我寫論文時發現了哪些非常神的網站?
- Python 編程的最好搭檔—VSCode 詳細指南