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的Django框架编写从Google Adsense中获得报表的应用
Apr 17 Python
django基础之数据库操作方法(详解)
May 24 Python
使用python生成目录树
Mar 29 Python
Python实现基于POS算法的区块链
Aug 07 Python
python识别图像并提取文字的实现方法
Jun 28 Python
Python 解析pymysql模块操作数据库的方法
Feb 18 Python
Python实现多线程下载脚本的示例代码
Apr 03 Python
django自带的权限管理Permission用法说明
May 13 Python
python用Tkinter做自己的中文代码编辑器
Sep 07 Python
浅析Python中字符串的intern机制
Oct 03 Python
Python中for后接else的语法使用
May 18 Python
七个非常实用的Python工具包总结
Jun 15 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 GeoIP的使用教程
2011/03/09 PHP
PHP写的获取各搜索蜘蛛爬行记录代码
2012/08/21 PHP
ThinkPHP函数详解之M方法和R方法
2015/09/10 PHP
PHP编写简单的App接口
2016/08/28 PHP
Symfony2创建基于域名的路由相关示例
2016/11/14 PHP
PHP+Session防止表单重复提交的解决方法
2018/04/09 PHP
php多进程并发编程防止出现僵尸进程的方法分析
2020/02/28 PHP
JQuery 学习笔记 选择器之六
2009/07/23 Javascript
javascript打印html内容功能的方法示例
2013/11/28 Javascript
javascript简单实现表格行间隔显示颜色并高亮显示
2013/11/29 Javascript
javascript中replace( )方法的使用
2015/04/24 Javascript
js匿名函数作为函数参数详解
2016/06/01 Javascript
javascript中数组和字符串的方法对比
2016/07/20 Javascript
浅谈jquery高级方法描述与应用
2016/10/04 Javascript
Sortable.js拖拽排序使用方法解析
2016/11/04 Javascript
如何实现json数据可视化详解
2016/11/24 Javascript
基于JS抓取某高校附近共享单车位置 使用web方式展示位置变化代码实例
2019/08/27 Javascript
微信小程序 SOTER 生物认证DEMO 指纹识别功能
2019/12/13 Javascript
jQuery实现颜色打字机的完整代码
2020/03/19 jQuery
Vue 的 v-model用法实例
2020/11/23 Vue.js
在nodejs中创建child process的方法
2021/01/26 NodeJs
详解Python用三种方式统计词频的方法
2019/07/29 Python
在python中利用dict转json按输入顺序输出内容方式
2020/02/27 Python
Django表单提交后实现获取相同name的不同value值
2020/05/14 Python
Python如何在循环内使用list.remove()
2020/06/01 Python
一份创业计划书范文
2014/02/08 职场文书
2014年教研工作总结
2014/12/06 职场文书
文明单位创建材料
2014/12/24 职场文书
前台接待员岗位职责
2015/04/15 职场文书
2015年工程师工作总结
2015/04/30 职场文书
学前教育见习总结
2015/06/23 职场文书
保险公司岗前培训工作总结
2015/10/24 职场文书
2019年二手房买卖合同范本
2019/10/14 职场文书
Python入门之基础语法详解
2021/05/11 Python
JavaScript的function函数详细介绍
2021/11/20 Javascript
Python可视化神器pyecharts绘制水球图
2022/07/07 Python