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线程锁(thread)学习示例
Dec 04 Python
python提取页面内url列表的方法
May 25 Python
Python 正则表达式入门(中级篇)
Dec 07 Python
Python实现按中文排序的方法示例
Apr 25 Python
值得收藏的10道python 面试题
Apr 15 Python
Python上下文管理器全实例详解
Nov 12 Python
PyQt5多线程刷新界面防假死示例
Dec 13 Python
Python对称的二叉树多种思路实现方法
Feb 28 Python
Django数据库操作之save与update的使用
Apr 01 Python
Python中的xlrd模块使用原理解析
May 21 Python
如何清空python的变量
Jul 05 Python
OpenCV图片漫画效果的实现示例
Aug 18 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
我常用的几个类
2006/10/09 PHP
Php中文件下载功能实现超详细流程分析
2012/06/13 PHP
Java和PHP在Web开发方面对比分析
2015/03/01 PHP
PHP 进度条函数的简单实例
2017/09/19 PHP
PHP将英文数字转换为阿拉伯数字实例讲解
2019/01/28 PHP
解决thinkPHP 5 nginx 部署时,只跳转首页的问题
2019/10/16 PHP
JavaScript中的style.display属性操作
2013/03/27 Javascript
用函数模板,写一个简单高效的 JSON 查询器的方法介绍
2013/04/17 Javascript
解析javascript系统错误:-1072896658的解决办法
2013/07/08 Javascript
jQuery+CSS3文字跑马灯特效的简单实现
2016/06/25 Javascript
javascript将中国数字格式转换成欧式数字格式的简单实例
2016/08/02 Javascript
浅谈javascript中遇到的字符串对象处理
2016/11/18 Javascript
通俗易懂地解释JS中的闭包
2017/10/23 Javascript
vue 实现边输入边搜索功能的实例讲解
2018/09/16 Javascript
通过实例讲解JS如何防抖动
2019/06/15 Javascript
快速解决element的autofocus失效问题
2020/09/08 Javascript
[00:47]DOTA2荣耀之路6:天火,天火!
2018/05/30 DOTA
python启动办公软件进程(word、excel、ppt、以及wps的et、wps、wpp)
2009/04/09 Python
python3实现读取chrome浏览器cookie
2016/06/19 Python
python实现生成字符串大小写字母和数字的各种组合
2019/01/01 Python
Django的用户模块与权限系统的示例代码
2019/07/24 Python
解决tensorflow由于未初始化变量而导致的错误问题
2020/01/06 Python
python基于property()函数定义属性
2020/01/22 Python
Python新手学习函数默认参数设置
2020/06/03 Python
python 多线程死锁问题的解决方案
2020/08/25 Python
Django Admin后台模型列表页面如何添加自定义操作按钮
2020/11/11 Python
Smashbox英国官网:美国知名彩妆品牌
2017/11/13 全球购物
保加利亚手表、香水、化妆品和珠宝购物网站:Brasty.bg
2020/04/22 全球购物
师范大学毕业自我鉴定
2013/11/21 职场文书
校园自助餐厅的创业计划书
2013/12/26 职场文书
班长竞选演讲稿
2014/04/24 职场文书
弘扬焦裕禄精神走群众路线思想汇报
2014/09/12 职场文书
群众路线组织生活会发言材料
2014/10/17 职场文书
2014年六五普法工作总结
2014/11/25 职场文书
《艾尔登法环》Boss腐烂树灵很有可能是《黑暗之魂3》的一个废案
2022/04/11 其他游戏
Java中的Kafka为什么性能这么快及4大核心详析
2022/09/23 Java/Android