python写一个多线程下载程序

简介

程序实现了多线程下载,在不支持断点续传时下载程序会采用单线程下载,可以自定义最大线程个数,程序会尝试尽可能多的线程去下载文件,如果因为使用太多线程而造成一些问题,也就是单个线程错误率达到设置最大错误率,将会自行减少线程个数,下载过程也会记录出错区间,然后插入到任务列表等待重新尝试下载,采用序列化工具以便下次下载同一个文件时依然能继续下载。

程序逻辑

每个url下载由一个Downloader类负责。

Downloader结构:

私有方法:
- _init_() 传入下载所需要的配置信息
- __init_task() 如果是新任务则初始化任务
- __init_from_conf() 如果任务已存在则从序列化文件中恢复
- __get_agent() 返回随机UA标识
- __itr_job() 返回任务区间
- __has_job() 判断是否仍有任务
- __download_no_206() 不支持断点续传时直接单线程下载
- __download_206() 支持断点续传时使用的函数
- __start_worker() 启动一个worker
- __start_workers() 启动多个worker
- __stopped() 单个线程结束后调用
- __after_stopped() 所有进程结束后调用

公有方法:
- start() 开始下载
- stop() 停止下载

写程序时遇到的一些问题:

1、当文件存在时需要续写也就是不希望删除文件内容,不能用wb,但也不能用ab,因为后者会迫使文件指针一直指向文件末尾,不能随意切换指针(使用seek()方法无效),而应该用rb+模式。

2、测试时遇到一个非常让人抓狂的问题是,在本地服务器测试无错,但是在百度找到的一个软件下载网站,太平洋软件下载网站测试时发现一直出错,后来发现该网站服务器竟然无法正确返回文件区间,后来换到ZOL软件下载网站ok

3、通过wireshark抓包可以发现直接用requests.get()方法每次都会发起一次TCP握手,这样非常不好,不仅会造成性能降低,还有可能因为发起多个连接而被服务器拒绝。所以应该在每个线程使用requests.session()进行get操作

查看代码

你可能感兴趣的:(python)