前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于 httpx/requests 的 异步 / 多线程 切片下载

基于 httpx/requests 的 异步 / 多线程 切片下载

原创
作者头像
懒py夏洛
发布2022-06-08 15:00:34
1.3K0
发布2022-06-08 15:00:34
举报
文章被收录于专栏:python爬虫与js逆向

作者: 懒

妥妥的论文标题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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档