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获取Linux下文件版本信息、公司名和产品名的方法
Oct 05 Python
浅谈python字典多键值及重复键值的使用
Nov 04 Python
Python中的单行、多行、中文注释方法
Jul 19 Python
Python实现针对json中某个关键字段进行排序操作示例
Dec 25 Python
如何用C代码给Python写扩展库(Cython)
May 17 Python
解决django 新增加用户信息出现错误的问题
Jul 28 Python
tensor和numpy的互相转换的实现示例
Aug 02 Python
通过Python编写一个简单登录功能过程解析
Sep 04 Python
基于python实现文件加密功能
Jan 06 Python
Python基于os.environ从windows获取环境变量
Jun 09 Python
关于Python不换行输出和不换行输出end=““不显示的问题(亲测已解决)
Oct 27 Python
Python爬虫Scrapy框架CrawlSpider原理及使用案例
Nov 20 Python
Python实现Telnet自动连接检测密码的示例
AI:如何训练机器学习的模型
python 用递归实现通用爬虫解析器
MATLAB 如何求取离散点的曲率最大值
用Python远程登陆服务器的步骤
Matlab求解数组中的最大值及它所在的具体位置
Apr 16 #Python
python 机器学习的标准化、归一化、正则化、离散化和白化
Apr 16 #Python
You might like
PHP 中的面向对象编程:通向大型 PHP 工程的办法
2006/12/03 PHP
PHP合并数组+与array_merge的区别分析
2010/08/01 PHP
php基础学习之变量的使用
2011/06/09 PHP
介绍一些PHP判断变量的函数
2012/04/24 PHP
PHP实现的封装验证码类详解
2013/06/18 PHP
php用户注册页面利用js进行表单验证具体实例
2013/10/17 PHP
Windows下wamp php单元测试工具PHPUnit安装及生成日志文件配置方法
2018/05/28 PHP
使用jQuery的ajax功能实现的RSS Reader 代码
2009/09/03 Javascript
Js切换功能的简单方法
2010/11/23 Javascript
javascript一元操作符(递增、递减)使用示例
2013/08/07 Javascript
js实现可拖动DIV的方法
2013/12/17 Javascript
对new functionName()定义一个函数的理解
2014/05/22 Javascript
jQuery中andSelf()方法用法实例
2015/01/08 Javascript
js运动动画的八个知识点
2015/03/12 Javascript
jquery实现标签支持图文排列带上下箭头按钮的选项卡
2015/03/14 Javascript
jQuery oLoader实现的加载图片和页面效果
2015/03/14 Javascript
javascript实现控制的多级下拉菜单
2015/07/05 Javascript
详解webpack-dev-server的简单使用
2018/04/02 Javascript
10分钟彻底搞懂Http的强制缓存和协商缓存(小结)
2018/08/30 Javascript
在Vue 中使用Typescript的示例代码
2018/09/10 Javascript
vue使用i18n实现国际化的方法详解
2019/09/05 Javascript
vue点击标签切换选中及互相排斥操作
2020/07/17 Javascript
使用基于Python的Tornado框架的HTTP客户端的教程
2015/04/24 Python
使用Python对Access读写操作
2017/03/30 Python
安装Python和pygame及相应的环境变量配置(图文教程)
2017/06/04 Python
Python基础教程之浅拷贝和深拷贝实例详解
2017/07/15 Python
使用canvas生成含有微信头像的邀请海报没有微信头像问题
2019/10/29 HTML / CSS
伦敦剧院及景点门票:Encore Tickets
2018/07/01 全球购物
全球性的奢侈品梦工厂:Forzieri(福喜利)
2019/02/20 全球购物
雅诗兰黛加拿大官网:Estee Lauder加拿大
2019/07/31 全球购物
正宗的日本零食和糖果订阅盒:Bokksu
2019/11/21 全球购物
全球领先的中国制造商品在线批发平台:DHgate
2020/01/28 全球购物
给医务人员表扬信
2014/01/12 职场文书
《月光启蒙》教学反思
2014/03/01 职场文书
实习报告评语
2014/04/26 职场文书
女生节标语
2014/06/26 职场文书