python下載mp4 同步和異步下載支持斷點續下







Range

用於請求頭中,指定第一個字節的位置和最后一個字節的位置,一般格式:

Range:(unit=first byte pos)-[last byte pos]

Range 頭部的格式有以下幾種情況:

Range: bytes=0-499 表示第 0-499 字節范圍的內容
Range: bytes=500-999 表示第 500-999 字節范圍的內容
Range: bytes=-500 表示最后 500 字節的內容
Range: bytes=500- 表示從第 500 字節開始到文件結束部分的內容
Range: bytes=0-0,-1 表示第一個和最后一個字節
Range: bytes=500-600,601-999 同時指定幾個范圍

原始響應內容¶
在罕見的情況下,你可能想獲取來自服務器的原始套接字響應,那么你可以訪問 r.raw。 如果你確實想這么干,那請你確保在初始請求中設置了 stream=True。具體你可以這么做:

r = requests.get('https://api.github.com/events', stream=True)
r.raw
<requests.packages.urllib3.response.HTTPResponse object at 0x101194810>

r.raw.read(10)
'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'
但一般情況下,你應該以下面的模式將文本流保存到文件:

with open(filename, 'wb') as fd:
for chunk in r.iter_content(chunk_size):
fd.write(chunk)
使用 Response.iter_content 將會處理大量你直接使用 Response.raw 不得不處理的。 當流下載時,上面是優先推薦的獲取內容方式。 Note that chunk_size can be freely adjusted to a number that may better fit your use cases.

# -*- coding: utf-8 -*-
# @Time : 2019/2/13 8:17 PM
# @Author : cxa
# @File : mp4downloders.py
# @Software: PyCharm
import requests
from tqdm import tqdm
import os
import base64
from cryptography.fernet import Fernet
import aiohttp
import asyncio
import uvloop

try:
    import uvloop

    asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
except ImportError:
    pass
keystr = "X0JxSkg4NFVBQVBPODlUM0VzT1liNnloeWtLcndkSldRT2xURzQ4MEM5RT0="


def get_aes_key():
    key = base64.b64decode(keystr).decode("utf8")
    return key


cipher = Fernet(get_aes_key())


def aes_cbc_decrypt(message):
    '''解密'''
    decrypted_text = Fernet(base64.b64decode(keystr).decode("utf8")).decrypt(
        bytes("{}".format(message), encoding="utf8"))
    return decrypted_text.decode("utf8")


def aes_cbc_encrypt(message):
    '''解密'''
    encrypted_text = cipher.encrypt(bytes("{}".format(message), encoding="utf8"))
    return encrypted_text


async def fetch(session, url, dst, pbar=None, headers=None):
    if headers:
        async with session.get(url, headers=headers) as req:
            with(open(dst, 'ab')) as f:
                while True:
                    chunk = await req.content.read(1024)
                    if not chunk:
                        break
                    f.write(chunk)
                    pbar.update(1024)
            pbar.close()
    else:
        async with session.get(url) as req:
            return req


async def async_download_from_url(url, dst):
    '''異步'''
    async with aiohttp.connector.TCPConnector(limit=300, force_close=True, enable_cleanup_closed=True) as tc:
        async with aiohttp.ClientSession(connector=tc) as session:
            req = await fetch(session, url, dst)

            file_size = int(req.headers['content-length'])
            print(f"獲取視頻總長度:{file_size}")
            if os.path.exists(dst):
                first_byte = os.path.getsize(dst)
            else:
                first_byte = 0
            if first_byte >= file_size:
                return file_size
            header = {"Range": f"bytes={first_byte}-{file_size}"}
            pbar = tqdm(
                total=file_size, initial=first_byte,
                unit='B', unit_scale=True, desc=dst)
            await fetch(session, url, dst, pbar=pbar, headers=header)

    #

    # req = requests.get(url, headers=header, stream=True)


def download_from_url(url, dst):
    '''同步'''
    response = requests.get(url, stream=True)
    file_size = int(response.headers['content-length'])
    if os.path.exists(dst):
        first_byte = os.path.getsize(dst)
    else:
        first_byte = 0
    if first_byte >= file_size:
        return file_size
    header = {"Range": f"bytes={first_byte}-{file_size}"}
    pbar = tqdm(
        total=file_size, initial=first_byte,
        unit='B', unit_scale=True, desc=dst)
    req = requests.get(url, headers=header, stream=True)
    with(open(dst, 'ab')) as f:
        for chunk in req.iter_content(chunk_size=1024):
            if chunk:
                f.write(chunk)
                pbar.update(1024)
    pbar.close()
    return file_size


if __name__ == '__main__':
    url = "xxxxx" #一個mp4鏈接即可。
    task = [asyncio.ensure_future(async_download_from_url(url, f"{i}.mp4")) for i in range(2, 14)]
    try:
        loop = asyncio.get_event_loop()
        loop.run_until_complete(asyncio.wait(task))
    except:
        loop.run_until_complete(loop.shutdown_asyncgens())
    finally:
        loop.close()

    # download_from_url(url, "1.mp4")


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM