Python实现多线程下载脚本的示例代码


Posted in Python onApril 03, 2020

0x01 分析

一个简单的多线程下载资源的Python脚本,主要实现部分包含两个类:

Download类:包含download()get_complete_rate()两种方法。

  • download()方法种首先用 urlopen() 方法打开远程资源并通过 Content-Length获取资源的大小,然后计算每个线程应该下载网络资源的大小及对应部分吗,最后依次创建并启动多个线程来下载网络资源的指定部分。
  • get_complete_rate()则是用来返回已下载的部分占全部资源大小的比例,用来回显进度。

ThreadDownload类:该线程类继承了threading.Thread类,包含了一个run()方法。

run()方法主要负责每个线程读取网络数据并写入本地。

0x02 代码

# 文件名:ThreadDownload.py
import threading
from urllib.request import *


class Download:
  def __init__(self, link, file_path, thread_num):
    # 下载路径
    self.link = link
    # 保存位置
    self.file_path = file_path
    # 使用多少线程
    self.thread_num = thread_num
    # 初始化threads数组
    self.threads = []

  def download(self):
    req = Request(url=self.link, method='GET')
    req.add_header('Accept', '*/*')
    req.add_header('Charset', 'UTF-8')
    req.add_header('Connection', 'Keep-Alive')
    f = urlopen(req)
    # 获取要下载的文件的大小
    self.file_size = int(dict(f.headers).get('Content-Length', 0))
    f.close()
    # 计算每个线程要下载的资源的大小
    current_part_size = self.file_size // self.thread_num + 1
    for i in range(self.thread_num):
      # 计算每个线程下载的开始位置
      start_pos = i * current_part_size
      # 每个线程使用一个wb模式打开的文件进行下载
      t = open(self.file_path, 'wb')
      t.seek(start_pos, 0)
      # 创建下载线程
      td = ThreadDownload(self.link, start_pos, current_part_size, t)
      self.threads.append(td)
      td.start()

  # 获下载的完成百分比
  def get_complete_rate(self):
    sum_size = 0
    for i in range(self.thread_num):
      sum_size += self.threads[i].length
    return sum_size / self.file_size

class ThreadDownload(threading.Thread):
  def __init__(self, link, start_pos, current_part_size, current_part):
    super().__init__() 
    # 下载路径
    self.link = link
    # 当前线程的下载位置
    self.start_pos = start_pos
    # 定义当前线程负责下载的文件大小
    self.current_part_size = current_part_size
    # 当前文件需要下载的文件快
    self.current_part = current_part
    # 定义该线程已经下载的字节数
    self.length = 0
  
  def run(self):
    req = Request(url = self.link, method='GET')
    req.add_header('Accept', '*/*')
    req.add_header('Charset', 'UTF-8')
    req.add_header('Connection', 'Keep-Alive')

    f = urlopen(req)
    # 跳过self.start_pos个字节,表明该线程只负责下载自己负责的那部分内容
    for i in range(self.start_pos):
      f.read(1)
    # 读取网络数据,并写入本地
    while self.length < self.current_part_size:
      data = f.read(1024)
      if data is None or len(data) <= 0:
        break
      self.current_part.write(data)
      # 累计该线程下载的总大小
      self.length += len(data)
    self.current_part.close()
    f.close()
#!/usr/bin/env python 
# -*- coding: utf-8 -*- 
# 文件名:thread_download-master.py

import sys
import time

from ThreadDownload import *


def show_process(dl):
  while dl.get_complete_rate() < 1:
    complete_rate = int(dl.get_complete_rate()*100) 
    print('\r' + '下载中···(已下载' + str(complete_rate) + '%)', end='', flush=True)
    time.sleep(0.01)


def main():
  try:  
    Link = input('[+]' + 'Link: ')
    file_path = input('[+]' + 'File Path: ')
    thread_number = input('[+]' + 'Thread Number: ')
    thread_number = int(thread_number)
    dl = Download(Link, file_path, thread_number)
    dl.download()
    print('\n开始下载!')
    show_process(dl)
    print('\r' + '下载中···(已下载' + '100%)', end='', flush=True)
    print('\n下载完成!')
  except Exception:
      print('Parameter Setting Error')
      sys.exit(1)

if __name__=='__main__':
    main()

0x03 运行结果

下载歌曲《男孩》为例,下载到./Download/目录下并命名为男孩.mp3,设置5个线程:

Python实现多线程下载脚本的示例代码

Python实现多线程下载脚本的示例代码

下载成功:

Python实现多线程下载脚本的示例代码

到此这篇关于Python实现多线程下载脚本的示例代码的文章就介绍到这了,更多相关Python 多线程下载脚本内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python实现全局变量的两个解决方法
Jul 03 Python
Python中字典的setdefault()方法教程
Feb 07 Python
python添加模块搜索路径方法
Sep 11 Python
python 顺时针打印矩阵的超简洁代码
Nov 14 Python
Python实现网页截图(PyQT5)过程解析
Aug 12 Python
详解Python3 中的字符串格式化语法
Jan 15 Python
python 截取XML中bndbox的坐标中的图像,另存为jpg的实例
Mar 10 Python
在Mac中配置Python虚拟环境过程解析
Jun 22 Python
解决Python3.8运行tornado项目报NotImplementedError错误
Sep 02 Python
地图可视化神器kepler.gl python接口的使用方法
Dec 22 Python
python 可视化库PyG2Plot的使用
Jan 21 Python
matplotlib之pyplot模块坐标轴标签设置使用(xlabel()、ylabel())
Feb 22 Python
python实现将两个文件夹合并至另一个文件夹(制作数据集)
Apr 03 #Python
pycharm安装及如何导入numpy
Apr 03 #Python
解决pyPdf和pyPdf2在合并pdf时出现异常的问题
Apr 03 #Python
Python利用PyPDF2库获取PDF文件总页码实例
Apr 03 #Python
Numpy 理解ndarray对象的示例代码
Apr 03 #Python
python计算Content-MD5并获取文件的Content-MD5值方式
Apr 03 #Python
Django自定义列表 models字段显示方式
Apr 03 #Python
You might like
ThinkPHP自动填充实现无限级分类的方法
2014/08/22 PHP
php图片的二进制转换实现方法
2014/12/15 PHP
如何用PHP做到页面注册审核
2017/03/02 PHP
关于php支持的协议与封装协议总结(推荐)
2017/11/17 PHP
phpmyadmin在宝塔面板里进不去的解决方案
2020/07/06 PHP
jQuery源码分析-03构造jQuery对象-工具函数
2011/11/14 Javascript
关于event.cancelBubble和event.stopPropagation()的区别介绍
2011/12/11 Javascript
裁剪字符串trim()自定义改进版
2013/04/10 Javascript
jQuery中实现动画效果的基本操作介绍
2013/04/16 Javascript
Js日期选择器并自动加入到输入框中示例代码
2013/08/02 Javascript
Angular.js中用ng-repeat-start实现自定义显示
2016/10/18 Javascript
Javascript es7中比较实用的两个方法示例
2017/07/21 Javascript
如何抽象一个Vue公共组件
2017/10/17 Javascript
vue axios登录请求拦截器
2018/04/02 Javascript
Node.js中,在cmd界面,进入退出Node.js运行环境的方法
2018/05/12 Javascript
讲解vue-router之什么是动态路由
2018/05/28 Javascript
vue-autoui自匹配webapi的UI控件的实现
2020/03/20 Javascript
vue3.0 的 Composition API 的使用示例
2020/10/26 Javascript
Python中turtle库的使用实例
2019/09/09 Python
selenium+python实现自动登陆QQ邮箱并发送邮件功能
2019/12/13 Python
基于matplotlib中ion()和ioff()的使用详解
2020/06/16 Python
Python爬虫爬取微博热搜保存为 Markdown 文件的源码
2021/02/22 Python
美国最大的烧烤架和户外生活用品专业零售商:Barbeques Galore
2021/01/09 全球购物
校长就职演讲稿
2014/01/06 职场文书
校园创业策划书
2014/01/14 职场文书
动漫专业高职生职业生涯规划书
2014/02/15 职场文书
初中军训感想300字
2014/03/05 职场文书
促销活动总结
2014/04/28 职场文书
充分就业社区汇报材料
2014/05/07 职场文书
个人委托书
2014/07/31 职场文书
见义勇为事迹材料
2014/12/24 职场文书
为自己工作观后感
2015/06/11 职场文书
大学军训口号大全
2015/12/24 职场文书
2016年基层党组织公开承诺书
2016/03/25 职场文书
JS 基本概念详细介绍
2021/10/16 Javascript
Spring Boot 实现 WebSocket
2022/04/30 Java/Android