python 爬虫 m3u8 视频文件 加密解密 整合mp4
文章目录
- 一、完整代码
- 二、视频分析
- 1. 认识m3u8文件
- 2. 获取密钥,构建解密器
- 3. 下载ts文件
- 4. 合并ts文件为mp4
- 三、总结
一、完整代码
完整代码如下:
import requests
from multiprocessing import Pool
import re
import os
from tqdm import tqdm
from Crypto.Cipher import AES# 创建临时文件夹
dirs = 'ts_list_need_to_merge/'
os.makedirs(dirs, exist_ok=True)headers = {'Accept': '*/*','Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6','Connection': 'keep-alive','Origin': 'http://www.kpd510.me','Referer': 'http://www.kpd510.me/','Sec-Fetch-Dest': 'empty','Sec-Fetch-Mode': 'cors','Sec-Fetch-Site': 'cross-site','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.69','sec-ch-ua': '"Chromium";v="116", "Not)A;Brand";v="24", "Microsoft Edge";v="116"','sec-ch-ua-mobile': '?0','sec-ch-ua-platform': '"Windows"',}def parse_m3u8_text(m3u8_text):m3u8_text = m3u8_text.split()encode_info = [line for line in m3u8_text if line.startswith('#EXT-X-KEY:')][0]pattern = r"#EXT-X-KEY:METHOD=(.*),URI=\"(.*)\"" ## 获得加密method 和 key.key的urlmatch = re.search(pattern, encode_info)if match:method = match.group(1)key_url = match.group(2)else:raise '解析失败'## 获得ts文件urlts_list = [line for line in m3u8_text if line.endswith('ts')]return method, key_url, ts_listdef decrypt_content_and_save_file(filename, content, decrypter):with open(filename, mode='wb') as f:f.write(decrypter.decrypt(content))def merge_ts_to_mp4(filename, ts_file_list):with open(filename, mode='ab') as f1:for ts_file in ts_file_list:with open(ts_file, mode='rb') as f2:f1.write(f2.read())print(filename, '完成!')def process_one_url(ts_url, key):decrypter = AES.new(key, AES.MODE_CBC)filename = dirs + os.path.split(ts_url)[-1]content = requests.get(ts_url, headers=headers).contentdecrypt_content_and_save_file(filename, content, decrypter)return filenamedef download_method_1(ts_list, key):# 普通次序一个一个下载,耗时11分钟ts_file_list = []for ts_url in tqdm(ts_list):filename = process_one_url(ts_url=ts_url, key=key)ts_file_list.append(filename)return ts_file_listdef download_method_2(ts_list, key, processes_nums=2):# 多进程下载, 耗时1分钟class CallBack:def __init__(self, nums) -> None:self.pbar = tqdm(total=nums)self.filenames = []def callback(self, filename):self.pbar.update(1)self.filenames.append(filename)callback = CallBack(len(ts_list))pool = Pool(processes=processes_nums)for ts_url in ts_list:pool.apply_async(process_one_url, (ts_url, key), error_callback=print, callback=callback.callback)pool.close()pool.join()callback.pbar.close()return [dirs + os.path.split(ts_url)[-1] for ts_url in ts_list]if __name__ == "__main__":m3u8_url = 'https://play.bo262626.com/20231108/xV1bY9Cn/700kb/hls/index.m3u8'response = requests.get(m3u8_url, headers=headers)m3u8 = response.textmethod, key_url, ts_list = parse_m3u8_text(m3u8)key_url = 'https://play.bo262626.com' + key_urlts_list = ['https://play.bo262626.com' + item for item in ts_list]key = requests.get(key_url, headers=headers).contentts_file_list = download_method_2(ts_list, key=key, processes_nums=10)merge_ts_to_mp4('test.mp4', ts_file_list)
二、视频分析
1. 认识m3u8文件
m3u8的结构详细分析可以看这个链接m3u8 文件格式详解 - 简书 (jianshu.com),这里我们只简要介绍一下;
相信无论多小白都应该知道如何打开开发者模型解析得到下面的结果;
要注意的是,只有预览里面包含了ts信息的才算是我们需要的m3u8文件;大家可以看到左侧有两个index.m3u8,其中一个是没有ts信息的,所以我们直接忽略掉;现在我们先下载来,再来具体分析一下m3u8文件以及里面的内容分别表达什么意思;
下载代码如下:
import requests
import reheaders = {'Accept': '*/*','Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6','Connection': 'keep-alive','Origin': 'http://www.kpd510.me','Referer': 'http://www.kpd510.me/','Sec-Fetch-Dest': 'empty','Sec-Fetch-Mode': 'cors','Sec-Fetch-Site': 'cross-site','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.69','sec-ch-ua': '"Chromium";v="116", "Not)A;Brand";v="24", "Microsoft Edge";v="116"','sec-ch-ua-mobile': '?0','sec-ch-ua-platform': '"Windows"',
}response = requests.get('https://play.bo262626.com/20231108/xV1bY9Cn/700kb/hls/index.m3u8', headers=headers)m3u8 = response.text
m3u8文件的实质是一个视频的url列表,其中ts是计算器可以直接播放的视频格式文件,但是直接下载是可能被加了密的文件,我们需要m3u8文件内容信息进行解密;
我们可以这样理解,m3u8把一个完整的mp4视频切割成了很多的小块,每一个小块在m3u8都是ts文件格式,并在m3u8中采取了加密的措施,至于为什么要加密,这里就不多介绍;
在一般的视频爬取中,我们只需要考虑两个部分,一个是EXT-X-KEY,一个是ts;
其中EXT-X-KEY包含了ts的加密方式,ts包含了ts文件的下载地址;
在红色部分也就是EXT-X-KEY部分,我们可以从METHOD中获取到采取的加密方式是AES-128,同时看到URI的地址/20231126/10VkaJks/700kb/hls/key.key,这也就是AES加密密匙的地址:key.key,接下来我们写一个文件来对m3u8文件解析,目的是提取出红色部分和蓝色部分;
代码如下:
def parse_m3u8_text(m3u8_text):m3u8_text = m3u8_text.split()encode_info = [line for line in m3u8_text if line.startswith('#EXT-X-KEY:')][0]pattern = r"#EXT-X-KEY:METHOD=(.*),URI=\"(.*)\"" ## 获得加密method 和 key.key的urlmatch = re.search(pattern, encode_info)if match:method = match.group(1)key_url = match.group(2)else:raise '解析失败'## 获得ts文件urlts_list = [line for line in m3u8_text if line.endswith('ts')]return method, key_url, ts_list## 在这里我们直接把m3u8文本丢进去就可以获得
## method, key_url, ts_list
method, key_url, ts_list = parse_m3u8_text(m3u8)
## method = 'AES-128'
## key_url = '/20231108/xV1bY9Cn/700kb/hls/key.key'
## ts_list = ['...ts', '...ts', ...]
2. 获取密钥,构建解密器
因为构建解密器我们需要密钥,而密钥存储在key.key中,首先我们需要解析key_url获取密钥;
在这里可以明显的看到key_url = '/20231108/xV1bY9Cn/700kb/hls/key.key'这不是一个完整的url,我们在这里加上获取m3u8请求的主域名便好;
代码如下:
headers = {'Accept': '*/*','Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6','Connection': 'keep-alive','Origin': 'http://www.kpd510.me','Referer': 'http://www.kpd510.me/','Sec-Fetch-Dest': 'empty','Sec-Fetch-Mode': 'cors','Sec-Fetch-Site': 'cross-site','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.69','sec-ch-ua': '"Chromium";v="116", "Not)A;Brand";v="24", "Microsoft Edge";v="116"','sec-ch-ua-mobile': '?0','sec-ch-ua-platform': '"Windows"',
}key_url = 'https://play.bo262626.com' + key_url
key = requests.get(key_url, headers=headers).content
# 这里我们得到key = b'388d590fabfeabcf' 是一个二进制结果
得到了密钥,再结合加密方式AES-128,我们就可以构建一个解密器,构建解密器代码如下:
from Crypto.Cipher import AES
## 这里网络爬取视频一般是MODE_CBC模式
decrypter = AES.new(key, AES.MODE_CBC)
这里要提起的是网络上的m3u8文件采取的加密一般是AES.MODE_CBC模式,在后续操作中如果这里出问题就换MODE一个一个试就好;
3. 下载ts文件
由于有许多的ts文件,我们有三种方法,第一是简单的requests请求一个一个下,这也是最费时的一种;第二个是多进程或者多线程的方式下载;第三个是采用协程的方式;接下来我们一个个实现;
在开始之间,ts_list存在同样的问题,就是需要重构url,这里代码如下:
ts_list = ['https://play.bo262626.com' + item for item in ts_list]# 这里得到:
# ['https://play.bo262626.com/20231108/xV1bY9Cn/700kb/hls/o3jSJ9mc.ts',
# 'https://play.bo262626.com/20231108/xV1bY9Cn/700kb/hls/GNHDlClJ.ts',
# 'https://play.bo262626.com/20231108/xV1bY9Cn/700kb/hls/zKym5c6V.ts',
# 'https://play.bo262626.com/20231108/xV1bY9Cn/700kb/hls/4ll4NQH3.ts',
# 'https://play.bo262626.com/20231108/xV1bY9Cn/700kb/hls/RwUOniSQ.ts' ...]
再测试一下解密器是否可以:
import os
from tqdm import tqdmdirs = 'ts_list_need_to_merge/'
os.makedirs(dirs, exist_ok=True)def decrypt_content_and_save_file(filename, content):with open(filename, mode='wb') as f:f.write(decrypter.decrypt(content))def process_one_url(ts_url, key):decrypter = AES.new(key, AES.MODE_CBC)filename = dirs + os.path.split(ts_url)[-1]content = requests.get(ts_url, headers=headers).contentdecrypt_content_and_save_file(filename, content, decrypter)return filenametest_content = requests.get(ts_list[0], headers=headers).content
decrypt_content_and_save_file('test.ts', test_content)## 打开视频看是否能打开
## 如果能打开说明解密没问题
直接requests: 代码如下
def download_method_1(ts_list, key):# 这里弄一个filename_list 方便后续合并ts到mp4ts_file_list = []for ts_url in tqdm(ts_list):filename = process_one_url(ts_url=ts_url, key=key)ts_file_list.append(filename)return ts_file_list# 下载测试
ts_file_list = download_method_1(ts_list, key)
实现挺慢的,不合理;
多进程: 代码如下
def download_method_2(ts_list, key, processes_nums=2):class CallBack:def __init__(self, nums) -> None:self.pbar = tqdm(total=nums)self.filenames = []def callback(self, filename):self.pbar.update(1)self.filenames.append(filename)callback = CallBack(len(ts_list))pool = Pool(processes=processes_nums)for ts_url in ts_list:pool.apply_async(process_one_url, (ts_url, key), error_callback=print, callback=callback.callback)pool.close()pool.join()callback.pbar.close()return [dirs + os.path.split(ts_url)[-1] for ts_url in ts_list]ts_file_list = download_method_2(ts_list, key=key, processes_nums=10)
爬取巨快,1分钟下载20多分钟的视频;
4. 合并ts文件为mp4
在完成前面的步骤后,直接ab的方式把所有的文件按顺序加入就好;
def merge_ts_to_mp4(filename, ts_file_list):with open(filename, mode='ab') as f1:for ts_file in ts_file_list:with open(ts_file, mode='rb') as f2:f1.write(f2.read())merge_ts_to_mp4('test.mp4', ts_file_list)
后续如果需要删除'ts_list_need_to_merge/'这个临时文件夹里面的所有内容,直接运行下面代码
import send2trashsend2trash.send2trash('ts_list_need_to_merge/') # send2trash.send2trash(dirs)
三、总结
别在图书馆测试这段代码!
相关文章:
python 爬虫 m3u8 视频文件 加密解密 整合mp4
文章目录 一、完整代码二、视频分析1. 认识m3u8文件2. 获取密钥,构建解密器3. 下载ts文件4. 合并ts文件为mp4 三、总结 一、完整代码 完整代码如下: import requests from multiprocessing import Pool import re import os from tqdm import tqdm fro…...
mybatis中xml文件容易搞混的属性
目录 第一章、1.1)MyBatis中resultMap标签1.2)MyBatis的resultType1.3)MyBatis的parameterType1.4)type属性1.5)jdbcType属性1.6)javaType属性1.7)ofType属性 友情提醒: 先看文章目录ÿ…...
android Retrofit2.0请求 延长超时操作
import okhttp3.OkHttpClient; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory;public class MyApiClient {private static final String BASE_URL "https://api.example.com/";// 创建 OkHttpClient,并设置超时时间…...
Axure之动态面板轮播图
目录 一.介绍 二.好处 三.动态面板轮播图 四.动态面板多方式登录 五.ERP登录 六.ERP的左侧菜单栏 七.ERP的公告栏 今天就到这了哦!!!希望能帮到你了哦!!! 一.介绍 Axure中的动态面板是一个非常有用的组…...
一文读懂算法中的时间复杂度和空间复杂度,O(1)、O(logn)、O(n)、O(n^2)、O(2^n) 附举例说明,常见的时间复杂度,空间复杂度
时间复杂度和空间复杂度是什么 时间复杂度(Time Complexity)是描述算法运行时间长短的一个度量。空间复杂度(Space Complexity)是描述算法在运行过程中所需要的存储空间大小的一个度量。 时间复杂度和空间复杂度是衡量算法性能…...
LWIP热插拔功能实现
0 工具准备 1.lwip 1.4.1 2.RTOS(本文使用rt-thread)1 使能连接变化回调功能 打开lwipopts.h,将宏定义LWIP_NETIF_LINK_CALLBACK的值设为1,如下: #define LWIP_NETIF_LINK_CALLBACK 1这个宏定义被使能后会将…...
android下的app性能测试应主要针对那些方面,如何开展?
如何开展安卓手机下的App性能测试,对于优秀的测试人员而言,除了要懂得性能测试的步骤流程外,还应该懂的性能测试的一些其他知识,比如性能测试指标、各指标的意义,常用的性能测试工具、如何查看结果分析等等知识。所以本…...
【深度学习】注意力机制(二)
本文介绍一些注意力机制的实现,包括EA/MHSA/SK/DA/EPSA。 【深度学习】注意力机制(一) 【深度学习】注意力机制(三) 目录 一、EA(External Attention) 二、Multi Head Self Attention 三、…...
学习黑马vue
项目分析 项目下载地址:vue-admin-template-master: 学习黑马vue 项目下载后没有环境可参考我的篇文章,算是比较详细:vue安装与配置-CSDN博客 安装这两个插件可格式化代码,vscode这个软件是免费的,官网:…...
gdb本地调试版本移植至ARM-Linux系统
移植ncurses库 本文使用的ncurses版本为ncurses-5.9.tar.gz 下载地址:https://ftp.gnu.org/gnu/ncurses/ncurses-5.9.tar.gz 1. 将ncurses压缩包拷贝至Linux主机或使用wget命令下载并解压 tar-zxvf ncurses-5.9.tar.gz 2. 解压后进入到ncurses-5.9目录…...
《Linux C编程实战》笔记:实现自己的ls命令
关键函数的功能及说明 1.void display_attribute(struct stat buf,char *name) 函数功能:打印文件名为name的文件信息,如 含义分别为:文件的类型和访问权限,文件的链接数,文件的所有者,文件所有者所属的组…...
Python个人代码随笔(观看无益,请跳过)
异常抛错:一般来说,在程序中,遇到异常时,会从这一层逐层往外抛错,一直抛到最外层,由最外层把错误显示在用户终端。 try:raise ValueError("A value error...") except ValueError:print("V…...
Unity中实现ShaderToy卡通火(总结篇)
文章目录 前言一、把卡通火修改为后处理效果1、在Shader属性面板定义属性接收帧缓存纹理2、在片元着色器对其纹理采样后,与卡通火相加输出请添加图片描述 二、我们自定义卡通火1、修改 _CUTOFF 使卡通火显示在屏幕两侧2、使火附近屏幕偏红色 前言 在之前的文章中&a…...
等保2.0的变化
1法律地位得到确认 《中华人民共和国网络安全法》第21条规定“国家实行网络安全等级保护制度”,要求“网络运营者应当按照网络安全等级保护制度要求,履行安全保护义务”;第31条规定“对于国家关键信息基础设施,在网络安全等级保护…...
漏洞复现-网神SecGate3600防火墙敏感信息泄露漏洞(附漏洞检测脚本)
免责声明 文章中涉及的漏洞均已修复,敏感信息均已做打码处理,文章仅做经验分享用途,切勿当真,未授权的攻击属于非法行为!文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直接或者间接的…...
ArkTS入门
代码结构分析 struct Index{ } 「自定义组件:可复用的UI单元」 xxx 「装饰器:用来装饰类结构、方法、变量」 Entry 标记当前组件是入口组件(该组件可被独立访问,通俗来讲:它自己就是一个页面)Component 用…...
JS中for循环之退出循环
我为大家介绍一下退出循环的两种方法 1.continue 退出本次循环,一般用于排除或者跳过某一个选项的时候,可以使用continue for(let i 0;i<5;i){if(i 3){continue}// 跳过了3console.log(i) //0 1 2 4}2.break 退出整个for循环,一般用于…...
《Global illumination with radiance regression functions》
总结一下最近看的这篇结合神经网络的全局光照论文。 论文的主要思想是利用了神经网络的非线性特性去拟合全局光照中的间接光照部分,采用了基础的2层MLP去训练,最终能实现一些点光源、glossy材质的光照渲染。为了更好的理解、其输入输出表示如下。 首先…...
华南理工C++试卷
诚信应考 , 考试作弊将带来严重后果! 《C程序设计试卷》 注意事项:1. 考前请将密封线内填写清楚; 2. 所有答案请答在试卷的答案栏上; 3.考试形式:闭卷 4. 本试卷共 五 大题,满分100分ÿ…...
0001.WIN7(64位)安装ADS1.2出现L6218错误
用了十多年的笔记本电脑系统出现问题,硬件升级重装以后安装ADS1.2。在编译代码的时候出现L6218错误。如下: 图片是从网上找的,我编译出错的界面没有保留下来。 首先,代码本身没有任何问题 ,代码在win7(32位)下编译没有…...
ubuntu25 安装ORG flow
下载ORG flow https://github.com/infiniflow/ragflow 上传至home文件夹下 进入文件夹/ragflow-main/docker下 安装docker: sudo snap install docker 安装gnome-terminal sudo apt install gnome-terminal sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL …...
CursorTouch融合交互:工业与医疗场景下人机协同新范式
1. 项目概述:从“CursorTouch/Operator-Use”看人机交互的范式革新最近在GitHub上看到一个名为“CursorTouch/Operator-Use”的项目,这个标题乍一看有点抽象,但作为一名长期关注人机交互(HMI)和工业自动化领域的老兵&a…...
从SK6812到WS2811:RoboMaster能量机关灯条平替方案全记录(附STM32 SPI+DMA配置代码)
从SK6812到WS2811:RoboMaster能量机关灯条平替方案全记录(附STM32 SPIDMA配置代码) 在RoboMaster等机器人竞赛中,能量机关的灯条效果直接影响视觉识别系统的稳定性。官方指定的SK6812灯珠虽性能优异,但每米144灯珠的高…...
3步搞定Windows风扇噪音:用免费软件实现智能散热控制
3步搞定Windows风扇噪音:用免费软件实现智能散热控制 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/fa/…...
新手入门,用外卖系统吃透Tomcat与Java Web全流程
对于刚接触Java Web的小伙伴来说,Tomcat、Servlet、端口号、网络请求这些概念,很容易越学越懵。今天全程用外卖系统做统一比喻,把复杂技术名词全部转化为生活场景,从零梳理Java Web核心流程,看完彻底理清浏览器、服务器…...
基于Roslyn为AI智能体生成C#代码地图:原理、实现与优化
1. 项目概述:为AI智能体绘制C#代码地图在AI智能体(Agent)技术日益成熟的今天,如何让这些“数字大脑”高效、准确地理解和操作复杂的代码库,成为了一个极具挑战性的工程问题。想象一下,你有一个精通C#的AI助…...
【独家首发】Midjourney啤酒印相失效诊断手册:识别8类常见色偏/纹理崩坏场景并实时修复
更多请点击: https://intelliparadigm.com 第一章:Midjourney Beer印相技术原理与失效本质 Midjourney Beer印相(非官方术语,实为社区对特定图像生成伪影的戏称)并非真实存在的官方技术,而是用户在使用 Mi…...
Midjourney Turbo模式实测报告:启动速度提升3.8倍、出图稳定性达99.2%——但92%用户根本没开对开关
更多请点击: https://intelliparadigm.com 第一章:Midjourney Turbo模式的核心价值与行业影响 加速生成与质量平衡的范式跃迁 Turbo 模式并非简单提速,而是通过动态计算图剪枝、低精度混合推理(FP16/INT8)及缓存感知…...
AI文本人性化工具:开源本地化改写方案与同义词替换原理
1. 项目概述与核心价值 最近在折腾一些文本内容,发现一个挺有意思的现象:无论是学生写论文、运营写文案,还是程序员写文档,大家或多或少都会用到AI工具来辅助生成初稿。这效率是上去了,但随之而来的问题也很明显——生…...
别再为固定输入尺寸发愁了:用PyTorch手把手实现SPP层(附完整代码)
突破固定尺寸限制:PyTorch实现空间金字塔池化的工程实践 在计算机视觉任务中,处理不同尺寸的输入图像一直是个令人头疼的问题。想象一下这样的场景:你正在开发一个目标检测系统,训练时所有图像都被统一调整为224224像素ÿ…...
