python解析视频

CGTN为例,想要获取里面视频。采用的播放器是JW player。

分析结构

播放视频,会发现视频文件是由一个个的ts文件拼接而来的。

其中,每一个小的ts是一个视频片段,只需要拼接就行了。
但是具体包含哪些片段呢,有另外一个请求可以看到。

在这个地方,可以看到由m3u8的请求可以看到,有四个版本的视频源,分别为高低清画质的。然后访问高画质的视频源,可以获取所有的ts文件。
最后,拼接一下ts文件即可。

python实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import re
import requests
name = "下载.mp4"
url = "https://video.cgtn.com/news/7767544e3567444d78496a4d3151444e35497a4e31457a6333566d54/video/4afe00b6e392433a91c70dabff85db6f/6000000-1920x1080/6000000-1920x1080.m3u8"

# 请求头,看网站更改
headers = {
"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",
}
r = requests.get(url)
t = re.compile(r"6000000.*?\.ts") # ts的正则匹配

ts_urls = t.findall(r.text) # ts的url列表
for ts_url in ts_urls:
ts_name = ts_url.split("/")[-1] # ts文件名
url1='https://video.cgtn.com/news/7767544e3567444d78496a4d3151444e35497a4e31457a6333566d54/video/4afe00b6e392433a91c70dabff85db6f/6000000-1920x1080/'
# 获取ts文件二进制数据
print("正在下载:" + ts_name)
fullurl=url1+ts_url
ts = requests.get(fullurl).content
with open(name, "ab") as file:
# # decrypt方法的参数需要为16的倍数,如果不是,需要在后面补二进制"0"
file.write(ts)
print("保存成功:" + ts_name)
print(name, "下载完成")

针对有一些网站的视频,在编码的时候进行了加密,一般有一个key的字段,解码的时候需要解密。
一般的解密:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 解密并保存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)
url1='https://video.cgtn.com/news/7767544e3567444d78496a4d3151444e35497a4e31457a6333566d54/video/4afe00b6e392433a91c70dabff85db6f/6000000-1920x1080/'
# 获取ts文件二进制数据
print("正在下载:" + ts_name)
fullurl=url1+ts_url
ts = requests.get(fullurl).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(ts)
print("保存成功:" + ts_name)