写在前面

为什么要多线程?单个线程不能下载吗?多线程能占满网络实现宽带的满速下载而单线程不能。

举个栗子:你的宽带是100Mb/s,理论上最大下载速度是100/8=12.5MB/s。你要下载一个843MB的视频,采用单线程下载你需要560秒才能下载完,而采用多线程(12个线程)你却可以在93秒内完成下载,时间将近缩短了6倍。

如果计算一下网络的利用率,你还可以发现:单线程的平均下载速度是1.50MB/s,而多线程的平均下载速度是9.06MB/s,多线程几乎将网络资源利用满了。这就是多线程的好处!

安装依赖

requests库用于从服务器请求资源。

pip3 install requests

测试样例

一个843MBMP4格式的视频文件。

https://gss3.baidu.com/6LZ0ej3k1Qd3ote6lo7D0j9wehsv/tieba-smallvideo/1250921_c7af3a2b73d03604f6421ef11134af72.mp4

多个线程

使用concurrent.futures模块的子类ThreadPoolExecutor创建线程池实现多线程。

from concurrent.futures import ThreadPoolExecutor
from requests import get, head
import timeclass downloader:def __init__(self, url, num, name):self.url = urlself.num = numself.name = nameself.getsize = 0r = head(self.url, allow_redirects=True)self.size = int(r.headers['Content-Length'])def down(self, start, end, chunk_size=10240):headers = {'range': f'bytes={start}-{end}'}r = get(self.url, headers=headers, stream=True)with open(self.name, "rb+") as f:f.seek(start)for chunk in r.iter_content(chunk_size):f.write(chunk)self.getsize += chunk_sizedef main(self):start_time = time.time()f = open(self.name, 'wb')f.truncate(self.size)f.close()tp = ThreadPoolExecutor(max_workers=self.num)futures = []start = 0for i in range(self.num):end = int((i+1)/self.num*self.size)future = tp.submit(self.down, start, end)futures.append(future)start = end+1while True:process = self.getsize/self.size*100last = self.getsizetime.sleep(1)curr = self.getsizedown = (curr-last)/1024if down > 1024:speed = f'{down/1024:6.2f}MB/s'else:speed = f'{down:6.2f}KB/s'print(f'process: {process:6.2f}% | speed: {speed}', end='\r')if process >= 100:print(f'process: {100.00:6}% | speed:  00.00KB/s', end=' | ')breaktp.shutdown()end_time = time.time()total_time = end_time-start_timeaverage_speed = self.size/total_time/1024/1024print(f'total-time: {total_time:.0f}s | average-speed: {average_speed:.2f}MB/s')if __name__ == '__main__':url = 'https://gss3.baidu.com/6LZ0ej3k1Qd3ote6lo7D0j9wehsv/tieba-smallvideo/1250921_c7af3a2b73d03604f6421ef11134af72.mp4'down = downloader(url, 12, 'test.mp4')down.main()

单个线程

import requests
import time
start = time.time()
url = 'https://gss3.baidu.com/6LZ0ej3k1Qd3ote6lo7D0j9wehsv/tieba-smallvideo/1250921_c7af3a2b73d03604f6421ef11134af72.mp4'
res = requests.get(url, stream=True)
with open('test.mp4', 'wb') as f:for chunk in res.iter_content(chunk_size=10240):f.write(chunk)
end = time.time()
print(end-start)

对比分析

同样下载一个843MB的视频,多线程和单线程的对比分析结果如下:

对比项 多线程 单线程
总计用时 93s 560s
平均速度 9.06MB/s 1.50MB/s

温馨提示

这里还和多线程网络下载器IDM对比了一下,发现用python实现的多线程下载器的下载速度并不亚于IDM,如果继续开发,实现断点续传和GUI后,应该可以完全替代IDM的下载功能。

未来展望

  • 多线程
  • 断点续传
  • GUI

引用参考

[0] https://blog.csdn.net/qq_41488943/article/details/107118377
[1] https://docs.python.org/zh-cn/3.8/library/concurrent.futures.html#threadpoolexecutor
[2] https://requests.readthedocs.io/zh_CN/latest/user/quickstart.html#id9

【python爬虫】实现多线程下载器相关推荐

  1. 用python爬虫制作图片下载器(超有趣!)

    这几天小菌给大家分享的大部分都是关于大数据,linux方面的"干货".有粉丝私聊小菌,希望能分享一些有趣的爬虫小程序.O(∩_∩)O哈哈,是时候露一手了.今天给大家分享的是一个适合 ...

  2. Python爬虫(二)——多线程下载壁纸图片(星月设计网)

    文章目录 Python爬虫--多线程下载图片(星月设计网) 目的: redis存储结构: 使用到的python库: 1. 导入相关库 2. 连接redis 3.爬虫主要类及函数 4.爬取结果: Pyt ...

  3. Python爬虫之网页下载器网页解析器

    一.网页下载器 -- urllib2的三种网页下载方法 import cookielib import urllib2url = "http://www.baidu.com" pr ...

  4. Python爬虫:URL管理器及其实现方式、网页下载器、网页解析器原理及其实现原理!

    Python爬虫之URL管理器: Python爬虫:URL管理器实现方式: Python爬虫之网页下载器: urllib2实现网页下载器的三种方法: 具体代码:                    ...

  5. 转:使用Python写一个m3u8多线程下载器

    转载:使用Python写一个m3u8多线程下载器 可去看原文:https://blog.csdn.net/muslim377287976/article/details/104340242 文章目录 ...

  6. 基于Python实现的网络爬虫项目——多线程下载小说并保存为txt文件(包含完整代码及注释)

    基于Python实现的网络爬虫项目--多线程下载小说并保存为txt文件(包含完整代码及注释) 一.确立预期目标 二.完成项目所需工具 三.项目需要解决的问题 问题一 问题二 问题三 问题四 问题五 问 ...

  7. Python:教你如何实现多线程下载器

    hello,大家好,我是wangzirui32,今天我们来学习如何使用Python实现多线程下载器,开始学习吧! 1. 流程&原理 将HEAD请求发送到目标URL,获取文件的大小 根据文件大小 ...

  8. 手把手教你实现一个 Python 多线程下载器

    前言 下载文件是我们生活中的一个常见的需求,因此衍生的下载工具也非常多,各有各的优势以及不足之处.作为一个编程爱好者,我喜欢去研究它们是怎么实现文件下载功能的. 我的主要使用的编程语言是 Python ...

  9. python多进程断点续传分片下载器

    python多进程断点续传分片下载器 标签:python 下载器 多进程 因为爬虫要用到下载器,但是直接用urllib下载很慢,所以找了很久终于找到一个让我欣喜的下载器.他能够断点续传分片下载,极大提 ...

最新文章

  1. 团体程序设计天梯赛 L2 题目合集
  2. android 自定义频谱,android – 如何从实时音频开发频谱分析仪?
  3. window服务器cpu过高的排查_线上服务器发生CPU占用率过高应该如何排查并定位问题?...
  4. 专业修复数据库修复软件不能修复的数据库
  5. 冲刺阶段(二) 第六天
  6. 怎么把微信机器人挂在服务器上,微信群机器人怎么弄的群里面的机器人怎么弄的???...
  7. 通过企业微信SCRM营销系统,完成百万私域用户引流
  8. sqlldr mysql_sqlldr数据导入
  9. QT使用PaddleOCR和百度OCR进行文字识别
  10. 【转】IOS数据库操作SQLite3使用详解
  11. Dreamweaver CS6 新建站点
  12. python的自省到底有什么用
  13. 华为海康大华摄像头编译RTSP转RTMP和HTTPFLV
  14. 震撼来袭!剪映专业版出内测了!最新功能抢先使用!
  15. 360°环视性能倍增,瑞芯微首发全景环视芯片方案
  16. 华为摄像机搜索软件_构建AI新生态,“软件定义”摄像机打造机器智能新捷径...
  17. 疫情下的通信人:你我的岁月静好,是谁在负重前行?
  18. 请编写程序,读入CSV文件中数据,循环获得用户输入,直至用户直接输入“Q”退出。根据用户输入的星座名称,输出此星座的出生日期范围及对应字符形式。如果输入的名称有误,请输出“输入星座名称有误”
  19. 计算机桌面不满屏怎样解决,图文教您电脑屏幕显示不满屏【操作措施】
  20. 百度联盟与Google AdSense的比较

热门文章

  1. 挑战坚持每天写算法题一个月
  2. 重装系统win11的步骤和详细教程
  3. Zookeeper开发者手册
  4. 第一次上传Git项目
  5. SharePoint Server 2016 Beta 版,中文版本安装出错的解决方案
  6. python开发酷q插件gui_【酷Q插件制作】教大家做一个简单的签到插件
  7. Mac控制台快捷键大全
  8. 基于Centos7.6安装Kibana7.3
  9. java的继承实例_java教程之java继承示例详解
  10. 富康/爱丽舍换挡时机