python进度条下载文件

python进度条下载文件

异步进度条:asyncio

环境:python3.7
库:需要安装aiohttp,tqdm,resquests
import asyncio
import aiohttp
from tqdm import tqdm


async def down_video(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(video_url, headers=headers) as resp:
            # 获取文件大小
            try:
                # 创建一个进度条,total文件长度,unit_scale=True设置显示下载速度k和m,ascii=True:windows控制台不换行,desc进度条前面的描述
                with tqdm(total=content_length, unit='', desc=f'下载:{name}', unit_divisor=1024, ascii=True, unit_scale=True) as bar:
                    content_length = resp.headers['content-length']
                    with open('文件名', 'rb+') as f:
                        # 一段一段的下载
                        async for chunk in resp.content.iter_chunked(1024):
                            f.write(chunk)
                            # 更新进度条
                            bar.update(len(chunk))
            except:
                print('文件不支持')
            

同步进度条resquests

import requests
from contextlib import closing
from tqdm import tqdm
# 设置stream=True为了不马上请求  colsing用来使用with管理上下文,不使用要关闭response
with closing(requests.get(video_url, stream=True, headers=headers)) as response:
    # 文件长度
    content_length = resp.headers['content-length']
    with open('文件名', 'rb+') as f:
        # 和前面的一样
        with tqdm(total=content_length, unit='', ascii=True, unit_scale=True) as bar:
            # 每次请求长度1024*10
            for chunk in response.iter_content(chunk_size=1024*10):
                if chunk:
                    f.write(chunk)
                    # 更新进度条
                    bar.update(1024*10)      

多协程asyncio


import asyncio
import aiohttp
from tqdm import tqdm
import os


class down_video():
    def __init__(self, headers=''):
        # 请求头
        self.__headers = headers

    def set_headers(self, new_headers):
        # 设置请求头
        self.__headers = new_headers

    async def __down_video(self, session, path, video_url, start, headers, bar):
        """
        :param path: 保存位置+名字
        :param session:
        :param video_url: 视频地址
        :param start: 视频开始写入位置
        :param headers: 请求头,包含请求长度和位置
        :param bar: 进度条
        """
        async with session.get(video_url, headers=headers) as resp:
            with open(path, 'rb+') as f:
                # 写入位置,指针移到指定位置
                f.seek(start)
                async for b in resp.content.iter_chunked(1024 * 1024):
                    f.write(b)
                    # 更新进度条,每次请求得到的长度
                    bar.update(len(b))

    async def __get_length(self, session, path, video_url):
        """创建和视频大小一样文件,并返回视频长度"""
        async with session.get(video_url, headers=self.__headers) as resp:
            # 获取视频长度
            le = int(resp.headers['Content-Length'])
            f = open(path, 'wb')
            f.truncate(le)
            f.close()
            return le

    async def __start_async(self, video_url, path, count=32):
        """
        :param video_url:视频地址
        :param path: 视频保存位置
        :param count:协程数量
        """
        path_, name = os.path.split(path)
        # 判断目录是否存在
        if not os.path.exists(path_):
            print('创建文件夹', path_)
            os.mkdir(path_)
        async with aiohttp.ClientSession() as session:
            # 文件长度
            content_length = await self.__get_length(session, path, video_url=video_url)
            
            # 每个协程爬取长度
            size = content_length // count
            args_list = []
            for i in range(count):
                start = i * size
                # 最后一个
                if i == count - 1:
                    end = content_length
                else:
                    end = start + size
                if start > 0:
                    start += 1
                # 设置请求视频位置
                headers = {
                    'Range': f'bytes={start}-{end}'
                }
                # 合并请求头
                headers.update(self.__headers)
                args = [session, path, video_url, start, headers]
                args_list.append(args)
            
            if args_list:
            	# total视频长度
                with tqdm(total=content_length, unit='', desc=f'下载:{name}', unit_divisor=1024, ascii=True,
                          unit_scale=True) as bar:
                    # 开始协程
                    await asyncio.wait([self.__down_video(*args, bar) for args in args_list])
            else:
                print('异常,有可能是请求头问题,或者视频地址不对,或者别的')

                
    def main(self, video_url, path, count=32):
        """
        :param video_url: 视频地址
        :param path: 保存地址
        :param count: 协程数量
        """
        asyncio.run(self.__start_async(video_url, path, count))


if __name__ == '__main__':
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0'
    }
    # 视频真实地址
    video_url = ''
    # 文件路径
    path = '3.flv'
    dv = down_video()
    # 设置请求头
    dv.set_headers(headers)
    # 开始
    dv.main(video_url, path)

效果

在这里插入图片描述

ps:下载前面速度还可以,后面就············

Python中,使用`requests`库下载文件时,可以通过自定义一个进度条显示下载进度。以下是一个基本的实现方法: 首先,需要安装`requests`库(如果尚未安装): ```bash pip install requests ``` 然后,可以使用以下代码来实现带有进度条文件下载: ```python import requests from tqdm import tqdm def download_file(url, file_name): # 发起请求并获取响应对象 response = requests.get(url, stream=True) # 确保请求成功 response.raise_for_status() # 获取文件总大小 total_size = int(response.headers.get('content-length', 0)) # 打开文件准备写入 with open(file_name, 'wb') as file: # 使用tqdm创建进度条 for data in tqdm(response.iter_content(1024), total=total_size/1024, unit='KB', unit_scale=True): # 将数据写入文件 file.write(data) # 使用示例 download_url = 'http://example.com/file.zip' # 替换为你需要下载文件链接 download_file(download_url, 'downloaded_file.zip') ``` 在上述代码中,`requests.get`用于发起网络请求,`stream=True`参数使得我们能够以流的方式处理数据,而不是一次性加载整个文件到内存。`response.iter_content`方法用于迭代文件内容,我们以1024字节为单位进行迭代,并使用`tqdm`库来创建和更新进度条。 注意,`tqdm`是一个快速、可扩展的Python进度条库,它可以在长循环中添加一个进度提示信息,用户只需要封装任意的迭代器`tqdm(iterator)`。如果你没有安装`tqdm`,可以通过以下命令安装: ```bash pip install tqdm ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值