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自动化测试之连接几组测试包实例
Sep 28 Python
Python中pip安装非PyPI官网第三方库的方法
Jun 02 Python
详解Python字符串对象的实现
Dec 24 Python
详解Python文本操作相关模块
Jun 22 Python
python探索之BaseHTTPServer-实现Web服务器介绍
Oct 28 Python
Python爬虫基础之XPath语法与lxml库的用法详解
Sep 13 Python
在unittest中使用 logging 模块记录测试数据的方法
Nov 30 Python
图解python全局变量与局部变量相关知识
Nov 02 Python
wxpython绘制圆角窗体
Nov 18 Python
解决redis与Python交互取出来的是bytes类型的问题
Jul 16 Python
python爬虫数据保存到mongoDB的实例方法
Jul 28 Python
Python selenium爬取微信公众号文章代码详解
Aug 12 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修改时间格式的代码
2011/05/29 PHP
PHP 自定义错误处理函数的使用详解
2013/05/10 PHP
怎样搭建PHP开发环境
2015/07/28 PHP
PHP读取目录树的实现方法分析
2019/03/22 PHP
Javascript客户端脚本的设计和应用
2006/08/21 Javascript
jQuery结合PHP+MySQL实现二级联动下拉列表[实例]
2011/11/15 Javascript
javascript 基础篇2 数据类型,语句,函数
2012/03/14 Javascript
jQuery UI Dialog 创建友好的弹出对话框实现代码
2012/04/12 Javascript
JS中Date日期函数中的参数使用介绍
2014/01/02 Javascript
JavaScript实现为input与textarea自定义hover,focus效果的方法
2015/08/21 Javascript
JQuery+EasyUI轻松实现步骤条效果
2016/02/22 Javascript
form表单转Json提交的方法(推荐)
2016/09/23 Javascript
关于JavaScript和jQuery的类型判断详解
2016/10/08 Javascript
js oncontextmenu事件使用详解
2017/03/25 Javascript
使用requirejs模块化开发多页面一个入口js的使用方式
2017/06/14 Javascript
浅谈js的解析顺序 作用域 严格模式
2017/10/23 Javascript
解决Vue2.0 watch对象属性变化监听不到的问题
2018/09/11 Javascript
vue input实现点击按钮文字增删功能示例
2019/01/29 Javascript
微信小程序获取地理位置及经纬度授权代码实例
2019/09/18 Javascript
[34:47]完美世界DOTA2联赛PWL S2 Magma vs LBZS 第一场 11.18
2020/11/18 DOTA
python遍历数组的方法小结
2015/04/30 Python
Python实现一个转存纯真IP数据库的脚本分享
2017/05/21 Python
python flask实现分页的示例代码
2018/08/02 Python
对Python之gzip文件读写的方法详解
2019/02/08 Python
多版本python的pip 升级后, pip2 pip3 与python版本失配解决方法
2019/09/11 Python
Flask 上传自定义头像的实例详解
2020/01/09 Python
Python文件名匹配与文件复制的实现
2020/12/11 Python
利于python脚本编写可视化nmap和masscan的方法
2020/12/29 Python
HTML5-WebSocket实现聊天室示例
2016/12/15 HTML / CSS
西班牙伏林航空公司:Vueling
2016/08/05 全球购物
秘鲁购物网站:Linio秘鲁
2017/04/07 全球购物
优秀毕业自我鉴定
2014/02/15 职场文书
村主任群众路线教育实践活动个人对照检查材料思想汇报
2014/10/01 职场文书
2014年党支部工作总结
2014/11/13 职场文书
元旦主持词开场白
2015/05/29 职场文书
2016元旦晚会主持词
2015/07/01 职场文书