当前位置: 首页 > 科技观察

每日一技能:轻松排雷,爬虫把Gzip炸弹变哑炮

时间:2023-03-18 01:48:03 科技观察

昨天的文章《??一日一技:反爬虫的极致手段,几行代码直接炸了爬虫服务器??》,讲到后端如何使用gzip返回压缩率极高的文件,瞬间卡死爬虫。大家都知道我的公众号作风,两头得罪人。昨天帮后台,今天帮爬虫。作为爬虫,如何避免踩到gzip炸弹?最直接的方法就是隐藏你的爬虫,因为gzip炸弹只有找到爬虫后才能使用,否则会影响正常用户。只要你的爬虫让网站无法被发现,那么自然不会踩到炸弹。如果你对隐藏爬虫没有把握,那么请继续往下看。查看gzip炸弹的url返回的Headers,会发现如下图所示的字段:只需要判断resp.headers中是否有名为content-encoding的字段,其值包含gzip或者deflate.如果没有这个字段,或者这个值不包含gzip或者deflate,那你大可放心,这很可能不是炸弹。值得一提的是,当你不读取resp.content和resp.text时,Requests不会擅自帮你解压,如下图。因此,您可以放心地检查Headers。:那么,如果发现网站返回的内容确实是gzip压缩后的内容怎么办?这时候我们不解压怎么才能得到解压后的大小呢?如果在本地查看一个.gz文件,那么可以使用命令gzip-lxxx.gz查看其头部信息:在打印出来的数据中,第一个数字是压缩后的大小,第二个数字是解压后的大小,第三个百分比是压缩率。这些信息保存在压缩文件的头部信息中,无需解压即可获得。那么我在使用Requests的时候,如何获取压缩后的二进制数据,并且防止未经授权解压呢?方法其实很简单:importrequestsresp=requests.get(url,stream=True)print(resp.raw.read())运行效果如下图所示:可以看到这个大小就是压缩的二进制数据。现在,我们可以使用下面的代码在不解压的情况下查询解压后的文件大小:decompressed),'rb')asg:g.seek(0,2)origin_size=g.tell()print(origin_size)运行效果如下图所示:打印出来的数字转换成MB是10MB,这是我们昨天测试的解压文件大小。通过这种方式,我们可以知道网站返回的gzip压缩数据在没有解压的情况下的实际大小。如果你发现实际大小大得离谱,你可以确定它是一个gzip炸弹并扔掉它。