作者: 懒
妥妥的论文标题hhh
最近也没搞啥新的逆向
but 由于最近工作需求 要写一个切片下载的功能
之前一直写js逆向的文章 今天来个python爬虫相关的吧hhh
应用场景:几百m的文件 网站限流 100k/s
该文章主要提供交流学习使用,请勿利用其进行不当行为!
如本篇文章应该不会侵犯贵公司了吧,我不删!
如因滥用(不是解密技术了吧)技术而产生的风险与本人无关!
1、切片下载的原理
首先 不是所有的下载都可以使用切片下载的,那怎么判断
主要是通过 headers 里面一个 特别的请求头 Range 实现的
简单来说 当使用 Range 参数后 服务器返回206 则代表支持切片下载
所以接下来切片下载需要实现的基本功能就如下:
1、判断是否支持切片功能,如果支持则顺带获取文件总大小
2、按指定的切片大小创建切片任务
3、并发下载
4、合并下载
(是不是和上面截图差不多 当然 正常流程就是这样子 但是实际设计过程中还有很多坑)
所以有一些附件功能
1、失败切片任务重试
2、缓存功能
3、异步模式和多线程模式
4、...
先解释下为啥又用了 httpx 又用了 requests
其实首先开发的时候是用的 aiohttp 后来发现他不支持 https 代理
然后就想着用 httpx 的异步。。结果使用代理请求部分https网站照样报错。。搜了下说是也不支持(找不到链接了) 所以就又写了多线程 requests的方式
开始开始(以下样例就以异步模式来讲吧,比较相对来说 多线程简单点):
首先是在基类的一些公共字段(用途看注释应该就行了)
download 方法流程如下
流程分析
1、判断是否有缓存 若有的话 则加载到内存中
2、判断是否支持切片功能并获取文件大小
看到文章说 使用 head 方法判断 实际上遇到过 光head 就以及很慢了的情况
所以我是直接构造 Range 下载 100b 的内容 来判断
如果状态码为 206 就是支持的 如果为200 则是不支持切片且直接下载完成了
其余均为异常情况
3、创建切片任务
根据文件总大小 和 切片大小 来计算 同时记录切片的序号 index
4、并发下载
先生成信号量控制并发 并创建异步任务
(多线程则用 ThreadPoolExecutor 控制并发就行)
每个切片下载前 先判断下缓存文件是否已下载(启用缓存功能的情况下)不存在则下载,对每个切片请求下来的大小做校验
成功的切片加入 success_list
重试后失败的切片加入 err_list
5、处理失败的情况
根据指定的失败列表重试次数去重试下载切片 如果重试还失败 就把成功下载的切片缓存下来 下次下载时只需要下载失败的部分就行了
6、都下载成功的情况下合并切片 可以对总大小再做一次校验
8、完整调用
异步模式:20s
多线程模式:20s
普通requests.get:等了8分钟了 不想等了。。
以上测试仅是当前参数下的结果 且可能存在网络波动hhhh
到此整个流程就完成了~
一些注意事项:
1、请使用python3.7 因为 asyncio.run 貌似是3.7 的语法 或者自行修改异步的语法就好了
2、有啥bug可以联系我撒,写完也没大量测试 可能还有坑没改hhh