zoukankan      html  css  js  c++  java
  • Python3 根据m3u8下载视频,批量下载ts文件并且合并

    Python3 根据m3u8下载视频,批量下载ts文件并且合并

    m3u8是苹果公司推出一种视频播放标准,是一种文件检索格式,将视频切割成一小段一小段的ts格式的视频文件,然后存在服务器中(现在为了减少I/o访问次数,一般存在服务器的内存中),通过m3u8解析出来路径,然后去请求,是现在比较流行的一种加载方式,诸如腾讯视频之类大多都是切割成ts流进行加载。

    示例代码:

    import os, shutil
    import urllib.request, urllib.error, requests
    
    # 打开并读取网页内容
    def getUrlData(url):
        try:
            urlData = urllib.request.urlopen(url, timeout=20)  # .read().decode('utf-8', 'ignore')
            return urlData
        except Exception as err:
            print(f'err getUrlData({url})
    ', err)
            return -1
    
    # 下载文件-urllib.request
    def getDown_urllib(url, file_path):
        try:
            urllib.request.urlretrieve(url, filename=file_path)
            return True
        except urllib.error.URLError as e:
            # hasttr(e, 'code'),判断e 是否有.code属性,因为不确定是不是HTTPError错误,URLError包含HTTPError,但是HTTPError以外的错误是不返回错误码(状态码)的
            if hasattr(e, 'code'):
                print(e.code)  # 打印服务器返回的错误码(状态码),如403,404,501之类的
            elif hasattr(e, 'reason'):
                print(e.reason)  # 打印错误原因
    
    
    def getVideo_urllib(url_m3u8, path, videoName):
        print('begin run ~~
    ')
         # urlData = getUrlData(url_m3u8).readlines()
        urlData = getUrlData(url_m3u8)
        num = 0
        tempName_video = os.path.join(path, f'{videoName}.ts')  # f'{}' 相当于'{}'.format() 或 '%s'%videoName
        # print(urlData)
        for line in urlData:
            # 解码,由于是直接使用了所抓取的链接内容,所以需要按行解码,如果提前解码则不能使用直接进行for循环,会报错
            # 改用上面的readlines()或readline()也可以,但更繁琐些,同样需要按行解码,效率更低
            url_ts = line.decode('utf-8')
            tempName_ts = os.path.join(path, f'{num}.ts')  # f'{}' 相当于'{}'.format()
            if not '.ts' in url_ts:
                continue
            else:
                if not url_ts.startswith('http'):  # 判断字符串是否以'http'开头,如果不是则说明url链接不完整,需要拼接
                    # 拼接ts流视频的url
                    url_ts = url_m3u8.replace(url_m3u8.split('/')[-1], url_ts)
            print(url_ts)
            getDown_urllib(url_ts, tempName_ts)  # 下载视频流
            if num == 0:
                # 重命名,已存在则自动覆盖
                shutil.move(tempName_ts, tempName_video)
                num += 1
                continue
            cmd = f'copy /b {tempName_video}+{tempName_ts} {tempName_video}'
            res = os.system(cmd)
            if res == 0:
                os.system(f'del {tempName_ts}')
                if num == 20:  # 限制下载的ts流个数,这个视频挺长有四百多个.ts文件,所以限制一下
                    break
                num += 1
                continue
            print(f'Wrong, copy {num}.ts-->{videoName}.ts failure')
            return False
        os.system(f'del {path}/*.ts')  # 调用windows命令行(即cmd)工具,运行命令
        filename = os.path.join(path, f'{videoName}.mp4')
        shutil.move(tempName_video, filename)
        print(f'{videoName}.mp4 finish down!')
    
    
    if __name__ == '__main__':
        url_m3u8 = 'http://wscdn.alhls.xiaoka.tv/201886/2f5/75a/HoHdTc1LjUaBjZbJ/index.m3u8'
        path = r'E:pydevworkspacesprojectproductepgwvideos'
        videoName = url_m3u8.split('/')[-2]
        getVideo_urllib(url_m3u8, path, videoName)

    注:(1)仅限windows下使用,如果要在Linux上使用需要修改合并命令;

            (2)修改文件名时,特意选择shutil模块(可以看作os的高级版)的move方法,虽然move主要是用来移动文件的,重命名算是附带的,不过强制覆盖的特点在这里很有用,避免中断后重新下载时重命名产生异常。

  • 相关阅读:
    Java实现 计蒜客 拯救行动
    Java实现 计蒜客 拯救行动
    Java实现 LeetCode 174 地下城游戏
    Java实现 LeetCode 174 地下城游戏
    Java实现 LeetCode 174 地下城游戏
    Java实现 LeetCode 173 二叉搜索树迭代器
    Java实现 LeetCode 173 二叉搜索树迭代器
    Visual Studio的SDK配置
    怎样使用CMenu类
    mfc menu用法一
  • 原文地址:https://www.cnblogs.com/lizm166/p/10262394.html
Copyright © 2011-2022 走看看