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 相关文章推荐
pyqt和pyside开发图形化界面
Jan 22 Python
使用Python开发windows GUI程序入门实例
Oct 23 Python
Python打印斐波拉契数列实例
Jul 07 Python
Python创建普通菜单示例【基于win32ui模块】
May 09 Python
django之跨表查询及添加记录的示例代码
Oct 16 Python
scrapy-redis源码分析之发送POST请求详解
May 15 Python
Python3基础教程之递归函数简单示例
Jun 07 Python
django的ORM操作 增加和查询
Jul 26 Python
Python for i in range ()用法详解
Sep 18 Python
python GUI库图形界面开发之PyQt5开发环境配置与基础使用
Feb 25 Python
scrapy-splash简单使用详解
Feb 21 Python
解决tensorflow模型压缩的问题_踩坑无数,总算搞定
Mar 02 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
PHP入门
2006/10/09 PHP
PHP扩展迁移为PHP7扩展兼容性问题记录
2016/02/15 PHP
Yii2中使用join、joinwith多表关联查询
2016/06/30 PHP
thinkPHP5实现数据库添加内容的方法
2017/10/25 PHP
用js自动判断浏览器分辨率的代码
2007/01/28 Javascript
网易JS面试题与Javascript词法作用域说明
2010/11/09 Javascript
js判断横竖屏及禁止浏览器滑动条示例
2014/04/29 Javascript
node.js中使用node-schedule实现定时任务实例
2014/06/03 Javascript
用js替换除数字与逗号以外的所有字符的代码
2014/06/07 Javascript
js实现当前输入框高亮显示的方法
2015/08/19 Javascript
详解JavaScript的AngularJS框架中的作用域与数据绑定
2016/03/04 Javascript
详解JS正则replace的使用方法
2016/03/06 Javascript
有关JavaScript中call()和apply() 的一些理解
2016/05/20 Javascript
jquery心形点赞关注效果的简单实现
2016/11/14 Javascript
JS实现快速比较两个字符串中包含有相同数字的方法
2017/09/11 Javascript
JS实现十字坐标跟随鼠标效果
2017/12/25 Javascript
vue-router启用history模式下的开发及非根目录部署方法
2018/12/23 Javascript
小程序实现搜索框
2020/06/19 Javascript
javascript面向对象创建对象的方式小结
2019/07/29 Javascript
vue data变量相互赋值后被实时同步的解决步骤
2020/08/05 Javascript
在Python中移动目录结构的方法
2016/01/31 Python
python之文件的读写和文件目录以及文件夹的操作实现代码
2016/08/28 Python
python将字符串list写入excel和txt的实例
2019/07/20 Python
HTML的form表单和django的form表单
2019/07/25 Python
Python基础教程之输入输出和运算符
2020/07/26 Python
python 基于opencv 实现一个鼠标绘图小程序
2020/12/11 Python
Dyson戴森波兰官网:Dyson.pl
2019/08/05 全球购物
铭宣海淘转运:美国、日本、英国转运等全球转运公司
2019/09/10 全球购物
奉献家乡演讲稿
2014/09/13 职场文书
入党积极分子自我批评思想汇报
2014/10/10 职场文书
2015年乡镇科普工作总结
2015/05/13 职场文书
分家协议书范本
2016/03/22 职场文书
学会掌握自己命运的十条黄金法则:
2019/08/08 职场文书
《家世》读后感:看家训的力量
2019/12/30 职场文书
Python入门学习之类的相关知识总结
2021/05/25 Python
MySQL开启事务的方式
2021/06/26 MySQL