python3.6根据m3u8下载mp4视频
作者:李嘉坤 发布时间:2021-05-22 00:20:03
需要下载某网站的视频,chrome浏览器按F12打开开发者模式,发现视频链接是以"blob:http"开头的链接,打开这个链接后找不到网页,网上查了下,找到了下载方法,在这里做个记录,如果有错误,欢迎指出。
程序在Windows 10下运行,不过Linux应该也没问题。
使用到的有re模块,requests模块和Crypto模块,其中requests模块和Crypto模块如果没安装可以使用pip命令安装。(Crypto模块安装感觉比较坑,我是从anaconda里拷贝了一份)
下面开始正题:
注:以下使用的m3u8文件所在的网站是自己搭建用来测试的,链接可能会失效。
首先在chrome的network里找到一个m3u8文件的请求,可以通过它下载视频。
通过Preview可以看到m3u8文件的内容。
这里m3u8文件比较重要的内容有两个。
一个是URI后面的链接,这个是加密和解密的秘钥,如果m3u8文件里有这个URI,那么这个视频就是经过了加密的,加密的方法可以看URI前面,这里是AES-128加密算法。
另一个是以ts结尾链接,这个是视频片段,如果是没进行加密的,可以直接打开这个链接下载视频片段,下载下来的是后缀为ts的文件,一般可以直接播放,不过时间很短。如果是加密过的,下载后播放会提示视频文件已损坏。
知道这些后,就可以进行下载了,先获取m3u8文件的内容,然后解析出秘钥(key)和ts的链接,然后下载key对每一个ts进行解密,保存到一个mp4文件里。
下载用的是requests模块,解析key和ts的链接是用的re模块,解密用的是Crypto模块。
使用Crypto需要注意三个地方,一个是安装和导入,第二个是Crypto里AES.new的参数,第三个是decrypt方法的参数。下面先看代码。
导入模块:
import re
import requests
from Crypto.Cipher import AES
初始设置:
# 保存的mp4文件名
name = "dream_it_possible.mp4"
# m3u8文件的url
url = "http://www.jiuyi.info/static/video/secret/dream_it_possible.m3u8"
# 请求头,不一定需要,看网站更改
headers = {
"Referer": "http://www.jiuyi.info/video/dream_it_possible",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36",
}
获取m3u8文件内容,并解析出key和ts文件的url。
# 获取m3u8文件内容
r = requests.get(url)
# 通过正值表达式获取key和ts的url
k = re.compile(r"http://.*?\.key") # key的正则匹配
t = re.compile(r"http://.*?\.ts") # ts的正则匹配
key_url = k.findall(r.text)[0] # key的url
ts_urls = t.findall(r.text) # ts的url列表
下载并解密ts文件,保存为mp4文件。
# 下载key
key = requests.get(key_url).content
# 解密并保存ts
for ts_url in ts_urls:
ts_name = ts_url.split("/")[-1] # ts文件名
# 解密,new有三个参数,
# 第一个是秘钥(key)的二进制数据,
# 第二个使用下面这个就好
# 第三个IV在m3u8文件里URI后面会给出,如果没有,可以尝试把秘钥(key)赋值给IV
sprytor = AES.new(key, AES.MODE_CBC, IV=key)
# 获取ts文件二进制数据
ts = requests.get(ts_url).content
# 密文长度不为16的倍数,则添加二进制"0"直到长度为16的倍数
while len(ts) % 16 != 0:
ts += b"0"
# 写入mp4文件
with open(name, "ab") as file:
# decrypt方法的参数需要为16的倍数,如果不是,需要在后面补二进制"0"
file.write(sprytor.decrypt(ts))
print(name, "下载完成")
到这里就下载完成了。
完整代码:
import re
import requests
from Crypto.Cipher import AES
# 保存的mp4文件名
name = "dream_it_possible.mp4"
# m3u8文件的url
url = "http://www.jiuyi.info/static/video/secret/dream_it_possible.m3u8"
# 请求头,不一定需要,看网站更改
headers = {
"Referer": "http://www.jiuyi.info/video/dream_it_possible",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36",
}
print("正在解析:" + url.split("/")[-1])
# 获取m3u8文件内容
r = requests.get(url)
# 通过正值表达式获取key和ts的链接
k = re.compile(r"http://.*?\.key") # key的正则匹配
t = re.compile(r"http://.*?\.ts") # ts的正则匹配
key_url = k.findall(r.text)[0] # key的url
ts_urls = t.findall(r.text) # ts的url列表
# 下载key的二进制数据
print("正在下载key")
key = requests.get(key_url).content
# 解密并保存ts
for ts_url in ts_urls:
ts_name = ts_url.split("/")[-1] # ts文件名
# 解密,new有三个参数,
# 第一个是秘钥(key)的二进制数据,
# 第二个使用下面这个就好
# 第三个IV在m3u8文件里URI后面会给出,如果没有,可以尝试把秘钥(key)赋值给IV
sprytor = AES.new(key, AES.MODE_CBC, IV=key)
# 获取ts文件二进制数据
print("正在下载:" + ts_name)
ts = requests.get(ts_url).content
# 密文长度不为16的倍数,则添加b"0"直到长度为16的倍数
while len(ts) % 16 != 0:
ts += b"0"
print("正在解密:" + ts_name)
# 写入mp4文件
with open(name, "ab") as file:
# # decrypt方法的参数需要为16的倍数,如果不是,需要在后面补二进制"0"
file.write(sprytor.decrypt(ts))
print("保存成功:" + ts_name)
print(name, "下载完成")
来源:https://blog.csdn.net/u012552769/article/details/87949543


猜你喜欢
- 需求:请求接口之后,缓存当前接口的数据,下次请求同一接口时拿缓存数据,不再重新请求添加缓存失效时间cache使用map来实现ES6 模块与
- python各类经纬度转换,具体代码如下所示:import mathimport urllibimport jsonx_pi = 3.141
- 一、如何将列表数据写入文件 ⾸先,我们来看看下⾯这段代码,并思考:这段代码有没有问题,如果有问题的话,要怎么改?li = [
- 需求问题在日常工作中,对于前端发送过来的请求,后端django大部分都是采用json格式返回,也有采用模板返回视图的方式。在模板返回视图的方
- 一、引言属性将值与类,结构体,枚举进行关联。Swift中的属性分为存储属性和计算属性两种,存储属性用于存储一个值,其只能用于类与结构体,计算
- 本文实例讲述了JavaScript中filter的用法。分享给大家供大家参考,具体如下:filterfilter也是一个常用的操作,它用于把
- 一、首先理解下面几个函数设置变量 length()函数 char_length() replace() 函数 max() 函数1.1、设置变
- 解决方法:先encode再quote。原理:msg.encode('utf-8')是解决中文乱码问题。quote():假如U
- 程序设计中我们时常需要检测用户输入是否正确,特别是姓名,地址等等是不是输入的汉字。那么,如何判断一个字符是不是汉字呢?其实在asp中至少有两
- #!/usr/bin/env python# -*- coding:utf-8-*-# file: {NAME}.py# @author:
- 本文实例讲述了mysql存储过程之游标(DECLARE)原理与用法。分享给大家供大家参考,具体如下:我们在处理存储过程中的结果集时,可以使用
- 视图层(view)视图函数,简称视图,本质上是一个简单的Python函数,它接受Web请求并且返回Web响应。响应的内容可以是HTML网页,
- 引言人工智能是计算机科学中一个非常热门的领域,近年来得到了越来越多的关注。它通过模拟人类思考过程和智能行为来实现对复杂任务的自主处理和学习,
- BULK INSERT以用户指定的格式复制一个数据文件至数据库表或视图中。 语法:BULK INSERT [ [ 'database
- 本文实例讲述了python通过apply使用元祖和列表调用函数的方法。分享给大家供大家参考。具体实现方法如下:def my_fuc(a, b
- 内置数据类型Python的内置数据类型既包括数值型和布尔型之类的标量,也包括 更为复杂的列表、字典和文件等结构。数值Python有4种数值类
- 自定义数据集在训练深度学习模型之前,样本集的制作非常重要。在pytorch中,提供了一些接口和类,方便我们定义自己的数据集合,下面完整的试验
- 1、例子:拟合一种函数Func,此处为一个指数函数。出处:SciPy v1.1.0 Reference Guide#Headerimport
- @property有什么用呢?表面看来,就是将一个方法用属性的方式来访问.上代码,代码最清晰了.class Circle(object):
- 本文实例为大家分享了python树莓派红外反射传感器的程序,供大家参考,具体内容如下1、工具rpi3,微雪ARPI600,Infrared