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('文件不支持')
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)
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:下载前面速度还可以,后面就············