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 相关文章推荐
Django Highcharts制作图表
Aug 27 Python
Python 爬虫学习笔记之多线程爬虫
Sep 21 Python
Python基于pygame模块播放MP3的方法示例
Sep 30 Python
django实现同一个ip十分钟内只能注册一次的实例
Nov 03 Python
详解K-means算法在Python中的实现
Dec 05 Python
pandas带有重复索引操作方法
Jun 08 Python
Python Datetime模块和Calendar模块用法实例分析
Apr 15 Python
PyQt5 窗口切换与自定义对话框的实例
Jun 20 Python
使用Keras预训练好的模型进行目标类别预测详解
Jun 27 Python
Python selenium环境搭建实现过程解析
Sep 08 Python
详解如何用Python实现感知器算法
Jun 18 Python
Python数据处理的三个实用技巧分享
Apr 01 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
smarty内置函数capture用法分析
2015/01/22 PHP
Laravel实现定时任务的示例代码
2017/08/10 PHP
php7函数,声明,返回值等新特性介绍
2018/05/25 PHP
PHP从尾到头打印链表实例讲解
2018/09/27 PHP
PHP变量的作用范围实例讲解
2020/12/22 PHP
JavaScript学习笔记(二) js对象
2011/10/25 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(四)用地图块拼成大地图
2013/01/23 Javascript
js中的push和join方法使用介绍
2013/10/08 Javascript
jquery隐藏标签和显示标签的实例
2013/11/11 Javascript
js的延迟执行问题分析
2014/06/23 Javascript
用简洁的jQuery方法toggleClass实现隔行换色
2014/10/22 Javascript
javascript中typeof操作符和constucor属性检测
2015/02/26 Javascript
Ext JS动态加载JavaScript创建窗体的方法
2016/06/23 Javascript
浅谈mint-ui loadmore组件注意的问题
2017/11/08 Javascript
JavaScript实现的简单加密解密操作示例
2018/06/01 Javascript
nodejs提示:cross-device link not permitted, rename错误的解决方法
2019/06/10 NodeJs
Vue.js中的extend绑定节点并显示的方法
2019/06/20 Javascript
layui select 禁止点击的实现方法
2019/09/05 Javascript
Vue项目中Api的组织和返回数据处理的操作
2019/11/04 Javascript
将Python中的数据存储到系统本地的简单方法
2015/04/11 Python
Django内容增加富文本功能的实例
2017/10/17 Python
利用Python代码实现数据可视化的5种方法详解
2018/03/25 Python
python pandas实现excel转为html格式的方法
2018/10/23 Python
学python安装的软件总结
2019/10/12 Python
Java Spring项目国际化(i18n)详细方法与实例
2020/03/20 Python
Python Request类源码实现方法及原理解析
2020/08/17 Python
scrapy-redis分布式爬虫的搭建过程(理论篇)
2020/09/29 Python
详解Python中的Lock和Rlock
2021/01/26 Python
Calphalon美国官网:美国顶级锅具品牌
2020/02/05 全球购物
Java Servlet的主要功能和作用是什么
2014/02/14 面试题
应聘护士求职信
2014/07/21 职场文书
教师学习党的群众路线教育实践活动心得体会
2014/10/31 职场文书
社区党支部承诺书
2015/04/29 职场文书
医院志愿者活动总结
2015/05/06 职场文书
企业员工辞职信范文
2015/05/12 职场文书
MySQL 原理优化之Group By的优化技巧
2022/08/14 MySQL