python3.6根据m3u8下载mp4视频


Posted in Python onJune 17, 2019

需要下载某网站的视频,chrome浏览器按F12打开开发者模式,发现视频链接是以"blob:http"开头的链接,打开这个链接后找不到网页,网上查了下,找到了下载方法,在这里做个记录,如果有错误,欢迎指出。

程序在Windows 10下运行,不过Linux应该也没问题。

使用到的有re模块,requests模块和Crypto模块,其中requests模块和Crypto模块如果没安装可以使用pip命令安装。(Crypto模块安装感觉比较坑,我是从anaconda里拷贝了一份)

下面开始正题:

注:以下使用的m3u8文件所在的网站是自己搭建用来测试的,链接可能会失效。

首先在chrome的network里找到一个m3u8文件的请求,可以通过它下载视频。

python3.6根据m3u8下载mp4视频

通过Preview可以看到m3u8文件的内容。

python3.6根据m3u8下载mp4视频

这里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, "下载完成")

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python的Django框架中if标签的相关使用
Jul 15 Python
python开发中range()函数用法实例分析
Nov 12 Python
Python内建数据结构详解
Feb 03 Python
Python实现读取SQLServer数据并插入到MongoDB数据库的方法示例
Jun 09 Python
python实现俄罗斯方块
Jun 26 Python
Python使用itchat 功能分析微信好友性别和位置
Aug 05 Python
python检查目录文件权限并修改目录文件权限的操作
Mar 11 Python
利用python控制Autocad:pyautocad方式
Jun 01 Python
如何解决flask修改静态资源后缓存文件不能及时更改问题
Aug 02 Python
理解Django 中Call Stack机制的小Demo
Sep 01 Python
Python使用内置函数setattr设置对象的属性值
Oct 16 Python
Python爬取梨视频的示例
Jan 29 Python
python如何实现视频转代码视频
Jun 17 #Python
python批量爬取下载抖音视频
Jun 17 #Python
python批量下载抖音视频
Jun 17 #Python
Python基础学习之类与实例基本用法与注意事项详解
Jun 17 #Python
python文本数据处理学习笔记详解
Jun 17 #Python
python3+PyQt5 实现Rich文本的行编辑方法
Jun 17 #Python
Appium+python自动化之连接模拟器并启动淘宝APP(超详解)
Jun 17 #Python
You might like
PHP strncasecmp字符串比较的小技巧
2011/01/04 PHP
PHP中替换键名的简易方法示例详解
2014/01/07 PHP
tp5(thinkPHP5)框架数据库Db增删改查常见操作总结
2019/01/10 PHP
PHP PDO数据库操作预处理与注意事项
2019/03/16 PHP
jquery json 实例代码
2010/12/02 Javascript
jQuery中判断一个元素是否为另一个元素的子元素(或者其本身)
2012/03/21 Javascript
JavaScript之编码规范 推荐
2012/05/23 Javascript
jQuery:节点(插入,复制,替换,删除)操作
2013/03/04 Javascript
JavaScript数组常用操作技巧汇总
2014/11/17 Javascript
NodeJS中Buffer模块详解
2015/01/07 NodeJs
在JavaScript中使用NaN值的方法
2015/06/05 Javascript
javascript数组排序汇总
2015/07/07 Javascript
js中字符串编码函数escape()、encodeURI()、encodeURIComponent()区别详解
2016/04/01 Javascript
JS与HTML结合使用marquee标签实现无缝滚动效果代码
2016/07/05 Javascript
微信小程序Redux绑定实例详解
2017/06/07 Javascript
手把手教你用Node.js爬虫爬取网站数据的方法
2018/07/05 Javascript
VUE 配置vue-devtools调试工具及安装方法
2018/09/30 Javascript
jqGrid表格底部汇总、合计行footerrow处理
2019/08/21 Javascript
小程序如何写动态标签的实现方法
2020/02/05 Javascript
[30:51]DOTA2上海特级锦标赛主赛事日 - 3 胜者组第二轮#1Liquid VS MVP.Phx第一局
2016/03/04 DOTA
[03:01]完美世界DOTA2联赛PWL S2 集锦第二期
2020/12/03 DOTA
一个检测OpenSSL心脏出血漏洞的Python脚本分享
2014/04/10 Python
python 执行shell命令并将结果保存的实例
2018/05/11 Python
在Pytorch中使用Mask R-CNN进行实例分割操作
2020/06/24 Python
Python代码覆盖率统计工具coverage.py用法详解
2020/11/25 Python
使用CSS3实现SVG路径描边动画效果入门教程
2019/10/21 HTML / CSS
HTML5的结构和语义(3):语义性的块级元素
2008/10/17 HTML / CSS
MONNIER Frères英国官网:源自巴黎女士奢侈品配饰电商平台
2018/12/06 全球购物
Groupon比利时官方网站:特卖和网上购物高达-70%
2019/08/09 全球购物
德国50岁以上交友网站:Lebensfreunde
2020/03/18 全球购物
电子商务应届生求职信
2013/11/16 职场文书
中学生校园广播稿
2014/01/16 职场文书
政治思想表现评语
2014/05/04 职场文书
体育教师求职信
2014/05/24 职场文书
2015年政务公开工作总结
2015/05/19 职场文书
python小型的音频操作库mp3Play
2022/04/24 Python