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运行时间的几种方法
Jun 17 Python
python学习笔记之列表(list)与元组(tuple)详解
Nov 23 Python
用Python实现KNN分类算法
Dec 22 Python
PyTorch线性回归和逻辑回归实战示例
May 22 Python
Python基于pyCUDA实现GPU加速并行计算功能入门教程
Jun 19 Python
python匹配两个短语之间的字符实例
Dec 25 Python
对python函数签名的方法详解
Jan 22 Python
python3检查字典传入函数键是否齐全的实例
Jun 05 Python
keras.layer.input()用法说明
Jun 16 Python
Python通过fnmatch模块实现文件名匹配
Sep 30 Python
python判断all函数输出结果是否为true的方法
Dec 03 Python
python向xls写入数据(包括合并,边框,对齐,列宽)
Feb 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手机号码归属地查询代码(API接口/mysql)
2012/09/04 PHP
Symfony模板的快捷变量用法实例
2016/03/17 PHP
PHP实现获取并生成数据库字典的方法
2016/05/04 PHP
学习ExtJS Panel常用方法
2009/10/07 Javascript
Js 回车换行处理的办法及replace方法应用
2013/01/24 Javascript
如何使用jquery控制CSS样式,并且取消Css样式(如背景色,有实例)
2013/07/09 Javascript
js数组操作学习总结
2013/11/04 Javascript
谈谈JavaScript自定义回调函数
2015/10/18 Javascript
基于javascript实现文字无缝滚动效果
2016/03/22 Javascript
JavaScript操作表单实例讲解(上)
2016/06/20 Javascript
JS之相等操作符详解
2016/09/13 Javascript
js变量提升深入理解
2016/09/16 Javascript
jquery自定义表单验证插件
2016/10/12 Javascript
利用CSS、JavaScript及Ajax实现图片预加载的三大方法
2017/01/22 Javascript
React Native中的RefreshContorl下拉刷新使用
2017/10/09 Javascript
vue-cli+webpack项目 修改项目名称的方法
2018/02/28 Javascript
JavaScript动态创建二维数组的方法示例
2019/02/01 Javascript
基于Vue 实现一个中规中矩loading组件
2019/04/03 Javascript
30分钟用Node.js构建一个API服务器的步骤详解
2019/05/24 Javascript
了解JavaScript中的选择器
2019/05/24 Javascript
vue实现评论列表功能
2019/10/25 Javascript
python实现Decorator模式实例代码
2018/02/09 Python
PyTorch的自适应池化Adaptive Pooling实例
2020/01/03 Python
python中pandas库中DataFrame对行和列的操作使用方法示例
2020/06/14 Python
Canvas波浪花环的示例代码
2020/08/21 HTML / CSS
德国网上药房:Apotal
2017/04/04 全球购物
Helly Hansen工作服美国官方网上商店:为最恶劣的环境
2019/09/04 全球购物
Shell编程面试题
2016/05/29 面试题
大学新学期计划书
2014/04/28 职场文书
小学优秀班主任事迹材料
2014/05/17 职场文书
供应商食品安全承诺书
2015/04/29 职场文书
小学班主任工作经验交流材料
2015/11/02 职场文书
维护民族团结心得体会2016
2016/01/15 职场文书
辞职申请书范本
2019/05/20 职场文书
python实现ROA算子边缘检测算法
2021/04/05 Python
AJAX实现省市县三级联动效果
2021/10/16 Javascript