你也可以手敲一个高速下载器(一)

353 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情


你也可以手敲一个高速下载器(一)

IDM的大名,大家应该都听过,具备高速下载文件和下载视频的功能,今天我们也来学习一下如何使用Python自己手敲一个高速下载器。

理论知识

基本知识

在同样网速的情况下,那些高速下载的软件是如何达到的那么高的速度呢?原因在就使用的HTTP协议里面,在HTTP协议中有一个响应头叫做:Accept-Ranges,如果获取这个响应的同时,存在这个字段并且值不为none,则说明该响应或资源支持断点续传,则在发生下一个请求的时候可以传递请求头:Range: bytes=0-x,其中0-x为请求资源的范围,这时响应的状态码为 206,响应的头会包含Content-Range字段,表示此次获取资源的范围,以及Content-Length字段表示此次响应的长度。

HEAD 请求

上面说过了,需要事先请求一个目标地址,才能确定下来,是否支持断点续传。这时,如果按照传统的做法,直接发送一个GET请求时间则会很长,断点也就没有意义了,所以这是可以发送一个HEAD请求,这个请求的意思是不会真正的获取资源,只是会获取对应的响应头和状态码。在这里就非常的实用了。

并发

了解了上面的知识,我想大家已经知道了如何打造这款高速下载工具,肯定是都知道了是使用并发同时去请求不同范围的资源,比如一个 328M 的资源,我们可以有多种不同的并发下载思路:

每个并发任务下载几乎相同大小的资源,下载一次

总大小 328M,设定并发数量为 32 个,则每个并发任务需要下载328*1024*1024 / 32 = 10747904 字节的资源,并且取整,在判断是否存在余数,存在余数则把余数的范围放到最后一个任务里面,这样的思路是任务的数量是固定的,每个任务只下载一次资源,最后整合

每个并发任务下载几乎相同大小的资源,下载多次

这种做法是和上面的思路类似,只不过是由下载一次变成了下载多次。总大小 328M,设定并发数量为 32 个,单个任务下载大小为 2M,则(328*1024*1024)/(1024*1024*2) = 164次,这时需要 32 个任务一共下载 164 次,如果结果是非整数则需向上取数保证完整性。

并发的选取

在 Python 中,关于并发可以选择进程池、线程池、异步,关于此内容可以查看我往期的内容:

开发的前置

这里说一下开发时需注意的问题,和需要事先考虑到的东西

异常的重试

由于是并发分段下载资源,对每段资源的完整性要求是很高的,任何一段资源的下载失败,都可能导致整个资源的失败,所以需要由一个健壮的异常重试机制,以保障我们的下载

资源的整合

同样由于是分段在下载,所以在下载结束我们就应该对所有的分段资源进行整合,这时我们可以选择:

  • 保存各个分段资源到真实目录下,最后整合,整合结束删除所有分段的资源
  • 保存各个分段资源到临时目录下,最后整合,整和结束后由系统自动删除所有分段资源
  • 保存各个分段资源到内存中,最后在内存中整合后直接保存至本地

各个方案都有各个方案的优缺点,其中保存在内容中当然是最快的,但如果程序崩溃也就失去了重新下载的可能性,而且一但资源大小超过了剩余内存大小则可能会出现问题,而临时目录下也会几率出现删除的可能性,真实目录下则会增多磁盘 IO 的读写删操作,需要去权衡方案的利弊

资源状态

由于部分的资源是需要验证才能下载的,这时就需要载入资源的cookies,或者有些资源需要特殊的请求头才可以进行下载,这时也需要载入资源的请求头,而有些资源的URL是会过期的,这时就需要一个刷新URL

程序的呈现形式

程序以那种呈现形式来运行,GUI的桌面程序,还是黑框框的终端命令行程序,命令行是交互式的还是参数式,每种方案的技术选型是哪种。

结语

这节主要说了一下开发的前置理论和开发之前需要考虑的技术范围,后面我们在来针对这些内容分别进行说明,敬请期待