python --m3u8下载和合并

python --m3u8下载和合并
代码如下:


import contextlib
import os
import tempfile
from urllib.parse import (
    splittype)

_url_tempfiles = []
from urllib import request
import requests



def Myurlretrieve(url, filename=None, reporthook=None, data=None, mode="ab"):
    """
    Retrieve a URL into a temporary location on disk.

    Requires a URL argument. If a filename is passed, it is used as
    the temporary file location. The reporthook argument should be
    a callable that accepts a block number, a read size, and the
    total file size of the URL target. The data argument should be
    valid URL encoded data.

    If a filename is passed and the URL points to a local resource,
    the result is a copy from local file to new file.

    Returns a tuple containing the path to the newly created
    data file as well as the resulting HTTPMessage object.
    """
    url_type, path = splittype(url)

    with contextlib.closing(request.urlopen(url, data)) as fp:
        headers = fp.info()

        # Just return the local path and the "headers" for file://
        # URLs. No sense in performing a copy unless requested.
        if url_type == "file" and not filename:
            return os.path.normpath(path), headers

        # Handle temporary file setup.
        if filename:
            tfp = open(filename, mode)
        else:
            tfp = tempfile.NamedTemporaryFile(delete=False)
            filename = tfp.name
            _url_tempfiles.append(filename)

        with tfp:
            result = filename, headers
            bs = 1024 * 8
            size = -1
            read = 0
            blocknum = 0
            if "content-length" in headers:
                size = int(headers["Content-Length"])

            if reporthook:
                reporthook(blocknum, bs, size)

            while True:
                block = fp.read(bs)
                if not block:
                    break
                read += len(block)
                tfp.write(block)
                blocknum += 1
                if reporthook:
                    reporthook(blocknum, bs, size)

    if size >= 0 and read < size:
        pass
        # raise ContentTooShortError(
        #     "retrieval incomplete: got only %i out of %i bytes"
        #     % (read, size), result)

    return result













class Url_ts():
    """
    通过一条url获取m3u8文件并下载其ts文件合并到.MP4
    """
    def __init__(self,url,filename="defualt.mp4"):
        """

        :param url: 下载m3u8文件地址
        :param filename: 文件名如."defualt.mp4"
        """
        self.url=url
        self.server=self.url.rsplit("/", 2)[0] + "/"
        download_path = os.getcwd() +r"\download/"
        if not os.path.exists(download_path):
            os.mkdir(download_path)
        self.filename=download_path+filename

    def getVideoTsUrl(self):
        """
        通过url 下载m3u8文件,读取m3u8文件获取.ts文件链接
        :param url: 下载m3u8文件的地址
        :return: yeild :ts文件地址
        """
        all_content = requests.get(url=self.url).text
        #  all_content = requests.get(url).text  # 获取M3U8的文件内容
        file_line = all_content.split("\n")  # 读取文件里的每一行
        # 通过判断文件头来确定是否是M3U8文件
        if file_line[0] != "#EXTM3U":
            raise BaseException(u"非M3U8的链接")
        else:
            unknow = True  # 用来判断是否找到了下载的地址
            for index, line in enumerate(file_line):
                if "EXT" in line:
                    unknow = False
                else:
                    if line != "":
                        pd_url =self.server + line
                        yield pd_url

            if unknow:
                raise BaseException("未找到对应的下载链接")

    def download_ts(self):
        """
        下载ts文件
        :return:
        """
        for url in self.getVideoTsUrl():
            print(url)
            Myurlretrieve(url=url, filename=self.filename, reporthook=self.Schedule, mode="ab")

    def Schedule(self,a, b, c):
        """
        进度条
        :param a:
        :param b:
        :param c:
        :return:
        """
        per = 100.0 * a * b / c
        if per > 100:
            per = 1
        print("  " + "%.2f%% 已经下载的大小:%ld 文件大小:%ld" % (per, a * b, c) + '\r')



    def run(self):
        self.download_ts()





if __name__ == '__main__':
    ts=Url_ts(url="https://vip.yingshidaqian.com/ppvod/209D602D37968D0C6A792E46491B9672.m3u8")
    ts.run()

执行效果如下:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

 with open(download_path + "\\" + "1.mp4", 'ab') as f:
                    f.write(res.content)
                    f.flush()

写入会有卡顿

猜你喜欢

转载自blog.csdn.net/huangwencai123/article/details/90449697