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 相关文章推荐
数据挖掘之Apriori算法详解和Python实现代码分享
Nov 07 Python
python利用urllib实现爬取京东网站商品图片的爬虫实例
Aug 24 Python
Python网络爬虫神器PyQuery的基本使用教程
Feb 03 Python
Python中循环后使用list.append()数据被覆盖问题的解决
Jul 01 Python
深入理解Django自定义信号(signals)
Oct 15 Python
实例介绍Python中整型
Feb 11 Python
使用python 的matplotlib 画轨道实例
Jan 19 Python
解决windows上安装tensorflow时报错,“DLL load failed: 找不到指定的模块”的问题
May 20 Python
python属于解释语言吗
Jun 11 Python
MATLAB数学建模之画图汇总
Jul 16 Python
requests在python中发送请求的实例讲解
Feb 17 Python
在python中读取和写入CSV文件详情
Jun 28 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
千呼万唤始出来,DOTA2勇士令状不朽宝藏Ⅱ现已推出
2020/08/25 DOTA
PHP中上传大体积文件时需要的设置
2006/10/09 PHP
ie6 动态缩略图不显示的原因
2009/06/21 PHP
通用PHP动态生成静态HTML网页的代码
2010/03/04 PHP
PHP得到某段时间区间的时间戳 php定时任务
2012/04/12 PHP
php排序算法(冒泡排序,快速排序)
2012/10/09 PHP
php5.3 不支持 session_register() 此函数已启用的解决方法
2013/11/12 PHP
php实现memcache缓存示例讲解
2013/12/04 PHP
PHP抓取网页、解析HTML常用的方法总结
2015/07/01 PHP
对laravel in 查询的使用方法详解
2019/10/09 PHP
Laravel5.1 框架响应基本用法实例分析
2020/01/04 PHP
基于jQuery的倒计时插件代码
2011/05/07 Javascript
多选列表框动态添加,移动,删除,全选等操作的简单实例
2014/01/13 Javascript
使用node+vue.js实现SPA应用
2016/01/28 Javascript
深入浅析JavaScript中的3DES
2016/08/24 Javascript
jquery+html仿翻页相册功能
2016/12/20 Javascript
vue.js的安装方法
2017/05/12 Javascript
jquery动态添加以及遍历option并获取特定样式名称的option方法
2018/01/29 jQuery
JS严格模式知识点总结
2018/02/27 Javascript
Vue props 单向数据流的实现
2018/11/06 Javascript
JavaScript常用内置对象用法分析
2019/07/09 Javascript
解决vue路由name同名,路由重复的问题
2020/08/05 Javascript
举例介绍Python中的25个隐藏特性
2015/03/30 Python
在Python中使用HTMLParser解析HTML的教程
2015/04/29 Python
python获取本地计算机名字的方法
2015/04/29 Python
pandas 对group进行聚合的例子
2019/12/27 Python
树莓派升级python的具体步骤
2020/07/05 Python
Kipling意大利官网:世界著名的时尚休闲包袋品牌
2019/06/05 全球购物
期末总结的个人自我评价
2013/11/02 职场文书
工商企业管理应届生求职信
2013/11/03 职场文书
计算机相关的自我评价
2014/01/15 职场文书
执法作风整顿剖析材料
2014/10/11 职场文书
2014年食堂工作总结
2014/11/20 职场文书
2014收银员工作总结范文
2014/12/16 职场文书
信访维稳承诺书
2015/05/04 职场文书
小学远程教育工作总结
2015/08/13 职场文书