Python通过m3u8文件下载合并ts视频的操作


Posted in Python onApril 16, 2021

前段时间,接到一个需求,要求下载某一个网站的视频,然后自己从网上查阅了相关的资料,在这里做一个总结。

1. m3u8文件

m3u8是苹果公司推出一种视频播放标准,是一种文件检索格式,将视频切割成一小段一小段的ts格式的视频文件,然后存在服务器中(现在为了减少I/o访问次数,一般存在服务器的内存中),通过m3u8解析出来路径,然后去请求,是现在比较流行的一种加载方式。目前,很多新闻视频网站都是采用这种模式去加载视频。

M3U8文件是指UTF-8编码格式的M3U文件。M3U文件是记录了一个索引纯文本文件,打开它时播放软件并不是播放它,而是根据它的索引找到对应的音视频文件的网络地址进行在线播放。原视频数据分割为很多个TS流,每个TS流的地址记录在m3u8文件列表中。

下面就是m3u8文件的格式。

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:15
#EXTINF:6.916667,
out000.ts
#EXTINF:10.416667,
out001.ts
#EXTINF:10.416667,
out002.ts
#EXTINF:1.375000,
out003.ts
#EXTINF:1.541667,
out004.ts
#EXTINF:7.666667,
out005.ts
#EXTINF:10.416667,

2. ts文件处理

只有m3u8文件,需要下载ts文件

ts文件能正常播放,但太多而小,需要合并 有ts文件

但因为被加密无法播放,需要解码

在这里我只记录下前两个步骤,因为,我目前研究的比较少,还没有遇到ts被加密的情况。

3. 分析举例

那么下面,我就正式举一个网站,第一财经网(直接点击)跟大家正式的讲解下。

这是该网站的视频。如下图:

Python通过m3u8文件下载合并ts视频的操作

点击第一个视频,这就是我们这次要爬取的视频。

Python通过m3u8文件下载合并ts视频的操作

然后鼠标右键点击,选择"检查" 或者按F12键,进入开发者模式,查看网页代码。

然后,点击Network ,再点击other,寻找请求地址中带有m3u8和ts标记的请求地址。

不懂,请看下图。有一点,很重要。网站通过切割后ts加载视频,并不是没有规律的,而是通过m3u8文件附带的。也就说,网站一定是先加载m3u8文件,然后根据m3u8文件,去请求ts文件。所以,如果你找不到m3u8文件的话,你可以先找第一个ts文件,然后往上面翻,一定能找到m3u8文件。

Python通过m3u8文件下载合并ts视频的操作

再点击这个m3u8文件,右侧对应的就是它的请求地址。

Python通过m3u8文件下载合并ts视频的操作

请求地址如下:

https://ycalvod.yicai.com/record/live/cbn/ca233887-1443-4bdf-b762-3b4b3a217085_LD.m3u8?auth_key=1575703722-0-0-6f09e9a156491f027a035e31c238c48c&ycfrom=yicaiwww

你可以把上面那个地址,输入浏览器地址框内,下载下来。也可以通过查看源码,找到该功能的对应的html代码。

这是下载下来的m3u8文件。

Python通过m3u8文件下载合并ts视频的操作

Python通过m3u8文件下载合并ts视频的操作

从图片可以看出来,每一个ts文件都是相对的地址,所以下面我们就需要找到绝对地址。

Python通过m3u8文件下载合并ts视频的操作

ts文件地址如下:

https://ycalvod.yicai.com/record/live/cbn_yld/1575111614_3446078.ts

上面,我们已经把这个网站的视频加载模式分析的很透彻,下面就开始撸代码了。

4. 获取ts文件

def getTsUrl():
    ts_url_list = []
    baseUrl = "https://ycalvod.yicai.com/record/live"
    with open("ca233887-1443-4bdf-b762-3b4b3a217085_LD.m3u8", "r", encoding="utf-8") as f:
        m3u8Contents = f.readlines()
        for content in m3u8Contents:
            if content.endswith("ts\n"):
                ts_Url = baseUrl + content.replace("\n", "").replace("..", "")
                ts_url_list.append(ts_Url)
                print(ts_Url)
    return ts_url_list

5. 下载ts文件

def download_ts_video(download_path, ts_url_list):
    download_path = r"C:\Users\Administrator\Desktop\AiShu\下载视频\TS视频"
    for i in range(len(ts_url_list)):
        ts_url = ts_url_list[i]
        try:
            response = requests.get(ts_url, stream=True, verify=False)
        except Exception as e:
            print("异常请求:%s" % e.args)
            return
        ts_path = download_path + "\{}.ts".format(i)
        with open(ts_path, "wb+") as file:
            for chunk in response.iter_content(chunk_size=1024):
                if chunk:
                    file.write(chunk)
    print("TS文件下载完毕!!")

这就是我本地下载好的ts切割视频

Python通过m3u8文件下载合并ts视频的操作

6. 合并TS视频

def heBingTsVideo(download_path,hebing_path):
    all_ts = os.listdir(download_path)
    with open(hebing_path, 'wb+') as f:
        for i in range(len(all_ts)):
            ts_video_path = os.path.join(download_path, all_ts[i])
            f.write(open(ts_video_path, 'rb').read())
    print("合并完成!!")

最后的结果如下:

Python通过m3u8文件下载合并ts视频的操作

7. 完整的代码

有兴趣的小伙伴,可以研究下。

import requests,os
def getTsUrl():
    ts_url_list = []
    baseUrl = "https://ycalvod.yicai.com/record/live"
    with open("ca233887-1443-4bdf-b762-3b4b3a217085_LD.m3u8", "r", encoding="utf-8") as f:
        m3u8Contents = f.readlines()
        for content in m3u8Contents:
            if content.endswith("ts\n"):
                ts_Url = baseUrl + content.replace("\n", "").replace("..", "")
                ts_url_list.append(ts_Url)
                print(ts_Url)
    return ts_url_list
def download_ts_video(download_path, ts_url_list):
    download_path = r"C:\Users\Administrator\Desktop\AiShu\下载视频\TS视频"
    for i in range(len(ts_url_list)):
        ts_url = ts_url_list[i]
        try:
            response = requests.get(ts_url, stream=True, verify=False)
        except Exception as e:
            print("异常请求:%s" % e.args)
            return
        ts_path = download_path + "\{}.ts".format(i)
        with open(ts_path, "wb+") as file:
            for chunk in response.iter_content(chunk_size=1024):
                if chunk:
                    file.write(chunk)
    print("TS文件下载完毕!!")
def heBingTsVideo(download_path,hebing_path):
    all_ts = os.listdir(download_path)
    with open(hebing_path, 'wb+') as f:
        for i in range(len(all_ts)):
            ts_video_path = os.path.join(download_path, all_ts[i])
            f.write(open(ts_video_path, 'rb').read())
    print("合并完成!!")
if __name__ == '__main__':
    download_path = r"C:\Users\Administrator\Desktop\AiShu\下载视频\TS视频"
    hebing_path = r"C:\Users\Administrator\Desktop\AiShu\下载视频\合并TS视频\第一财经.mp4"
    ts_url_list = getTsUrl()
    download_ts_video(download_path, ts_url_list)
    heBingTsVideo(download_path,hebing_path)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。如有错误或未考虑完全的地方,望不吝赐教。

Python 相关文章推荐
python网络编程学习笔记(四):域名系统
Jun 09 Python
python通过字典dict判断指定键值是否存在的方法
Mar 21 Python
Python sqlite3事务处理方法实例分析
Jun 19 Python
Python中的错误和异常处理简单操作示例【try-except用法】
Jul 25 Python
python 列表,数组,矩阵两两转换tolist()的实例
Apr 04 Python
python 把文件中的每一行以数组的元素放入数组中的方法
Apr 29 Python
对tf.reduce_sum tensorflow维度上的操作详解
Jul 26 Python
python使用epoll实现服务端的方法
Oct 16 Python
Python使用sklearn库实现的各种分类算法简单应用小结
Jul 04 Python
python 初始化一个定长的数组实例
Dec 02 Python
如何利用python web框架做文件流下载的实现示例
Jun 02 Python
python - asyncio异步编程
Apr 06 Python
Python实现Telnet自动连接检测密码的示例
AI:如何训练机器学习的模型
python 用递归实现通用爬虫解析器
MATLAB 如何求取离散点的曲率最大值
用Python远程登陆服务器的步骤
Matlab求解数组中的最大值及它所在的具体位置
Apr 16 #Python
python 机器学习的标准化、归一化、正则化、离散化和白化
Apr 16 #Python
You might like
菜鸟修复电子管记
2021/03/02 无线电
PHP常用函数和常见疑难问题解答
2014/03/05 PHP
PHP中UNIX时间戳和日期间的转换与计算实例
2014/11/19 PHP
不用AJAX和IFRAME,说说真正意义上的ASP+JS无刷新技术
2008/09/25 Javascript
jQuery select的操作实现代码
2009/05/06 Javascript
JavaScript Event事件学习第一章 Event介绍
2010/02/07 Javascript
json格式的时间显示为正常年月日的方法
2013/09/08 Javascript
JS实现时间格式化的方式汇总
2013/10/16 Javascript
浅析hasOwnProperty方法的应用
2013/11/20 Javascript
jquery插件开发之实现jquery手风琴功能分享
2014/03/10 Javascript
深入理解javascript原型链和继承
2014/09/23 Javascript
深入理解JavaScript系列(34):设计模式之命令模式详解
2015/03/03 Javascript
Javascript中的匿名函数与封装介绍
2015/03/15 Javascript
JS实现控制表格只显示行边框或者只显示列边框的方法
2015/03/31 Javascript
JS实现网页顶部向下滑出的全国城市切换导航效果
2015/08/22 Javascript
jQuery简单实现提交数据出现loading进度条的方法
2016/03/29 Javascript
jQuery Mobile中的button按钮组件基础使用教程
2016/05/23 Javascript
JS操作JSON方法总结(推荐)
2016/06/14 Javascript
用iframe实现不刷新整个页面上传图片的实例
2016/11/18 Javascript
详解webpack+angular2开发环境搭建
2017/06/28 Javascript
js学习总结之DOM2兼容处理重复问题的解决方法
2017/07/27 Javascript
分享6个隐藏的python功能
2017/12/07 Python
Python+matplotlib实现填充螺旋实例
2018/01/15 Python
Python实现的调用C语言函数功能简单实例
2019/03/13 Python
Win10下安装并使用tensorflow-gpu1.8.0+python3.6全过程分析(显卡MX250+CUDA9.0+cudnn)
2020/02/17 Python
pycharm 对代码做静态检查操作
2020/06/09 Python
Selenium 安装和简单使用的实现
2020/12/04 Python
pandas数据分组groupby()和统计函数agg()的使用
2021/03/04 Python
C面试题
2015/10/08 面试题
服务生自我鉴定
2014/01/22 职场文书
优秀幼教自荐信
2014/02/03 职场文书
加薪通知
2015/04/25 职场文书
25句企业管理语录:助你迅速打开思路,句句经典!
2020/01/14 职场文书
python 遍历磁盘目录的三种方法
2021/04/02 Python
MySQL 全文索引使用指南
2021/05/25 MySQL
浅谈如何提高PHP代码质量之端到端集成测试
2021/05/28 PHP