一日一技:轻松排雷,爬虫让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”,备注“粉丝群”(谢绝广告党,非诚勿扰!)
- 一日一技:如何批量给PDF添加水印?
- 一日一技:抛掉JavaScript,用HTML和Python做网站
- 一个让我感到 "细思极恐" 的开源项目!
- 一日一技:FastAPI 接口限流
- 5 分钟,使用内网穿透快速实现远程手机桌面!
- Python Delorean 优秀的时间格式智能转换工具
- 写在公众号粉丝2w时
- 一日一技:协程与多进程的完美结合
- 一个 "丧心病狂" 的开源项目
- python中如何优雅的实现代码与敏感信息分离?
- Pandas 多进程处理数据,速度快了不少!
- 爬虫出海Step by Step(一)
- 一日一知:架构到底是什么?
- Python识别花卉种类,并自动整理分类!
- 这几个摸鱼神器,你怎么能不知道
- FoolNLTK — 简单好用的中文NLP工具包
- 一日一知:国内爬虫开发人员的未来
- 我写论文时发现了哪些非常神的网站?
- Python 编程的最好搭档—VSCode 详细指南
- 一日一技:急速搭建问答搜索引擎