python爬取m3u8视频(思路到实现全讲解!!!)

文章目录

  • 抓取m3u8视频
    • 1、思路分析
    • 2、实现
      • 分析index.m3u8
    • 3、代码实现
      • 3.1 获取最后一个m3u8的url地址
      • 3.2 多线程下载ts文件与视频合并
      • 3.3 合并获取上面俩个代码段的代码
    • 4、注意事项
      • 4.1 说明
      • 4.2 使用代码进行处理
      • 4.3 完整代码
    • 5、解密处理
  • 处理m3u8文件中的url问题

抓取m3u8视频

1、思路分析

视频url:https://www.9meiju.cc/mohuankehuan/shandianxiadibaji/1-1.html

  1. 打开网址分析当前视频是由多个片段组成还是单独一个视频 如果是一个单独视频,则找到网址,直接下载即可,如果为多个片段的视频,则需要找到片段的文件进行处理,本案例以m3u8为例
  2. 找到m3u8文件后进行下载,下载后打开文件分析是否需要秘钥,需要秘钥则根据秘钥地址进行秘钥下载,然后下载所有ts文件
  3. 合并所有视频

2、实现

分析index.m3u8

  • 通过网络查找发现有俩个m3u8文件

    url分别为

    https://new.qqaku.com/20211117/iHVkqQMI/index.m3u8

    https://new.qqaku.com/20211117/iHVkqQMI/2523kb/hls/index.m3u8

    通过分析 第一个index.m3u8请求返回的内容中包含了第二个m3u8请求的url地址

    也就是说通过第一个index.m3u8url请求返回包含第二个index.m3u8文件地址,通过拼接请求第二个index.m3u8后 返回了包含当前所有ts文件的地址内容

    现在分析出了第二个真正的index.m3u8的地址,但是第一个地址从哪里来的呢,别慌,接下来我们来查找一下第一个url是从哪里来的

  • 查找第一个index.m3u8的url地址

    打开source

    发现url存在页面源代码中的js里 知道了位置,在代码中通过正则匹配就可以获取到了

    现在我们缕一下思路,通过页面源代码可以找到第一个index.m3u8的url,通过请求返回包含第二个index.m3u8文件的url内容,进行拼接,请求第二个m3u8的url,以此返回所有的ts内容

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3、代码实现

3.1 获取最后一个m3u8的url地址

import re
from urllib.parse import urljoinimport requestsheaders = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}session = requests.Session()
session.get('https://www.9meiju.cc/', headers=headers)url = 'https://www.9meiju.cc/mohuankehuan/shandianxiadibaji/1-2.html'
response = session.get(url, headers=headers)
response.encoding = 'UTF-8'
data = response.text
# print(data)
'''
<script>
var zanpiancms_player = {"player":"\/public\/","url":"https:\/\/new.qqaku.com\/20211124\/nLwncbZW\/index.m3u8","next":"https:\/\/www.9meiju.cc\/mohuankehuan\/shandianxiadibaji\/1-3.html","name":"wjm3u8","apiurl":null,"adtime":"0","adurl":"","copyright":0,"danmu":{"status":0}};
</script>
'''
# 正则抓取上面的源代码中的m3u8的url
m3u8_uri = re.search('"url":"(.+?index.m3u8)"', data).group(1).replace('\\', '')# 写入文件 分析当前的页面源代码
with open('99.html', 'w', encoding='UTF-8') as f:# 写入response.content bytes二进制类型f.write(response.content.decode('UTF-8'))# 请求可以获取index.m3u8文件
response = session.get(m3u8_uri, headers=headers)
with open('m3u8_uri.text', 'w', encoding='UTF-8') as f:# 写入response.content bytes二进制类型f.write(response.content.decode('UTF-8'))
response.encoding = 'UTF-8'
data = response.text# 拆分返回的内容获取真整的index.m3u8文件的url
url = data.split('/', 3)[-1]
print(data)
print('m3u8_uri', m3u8_uri)
print('url', url)
print(urljoin(m3u8_uri, url))

3.2 多线程下载ts文件与视频合并

import time
import requests
import os
from concurrent.futures import ThreadPoolExecutor, waitheaders = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36"
}def down_video(url, i):'''下载ts文件:param url::param i::return:'''# print(url)# 下载ts文件resp = requests.get(url, headers=headers)with open(os.path.join(path, str(i)+'.ts'), mode="wb") as f3:f3.write(resp.content)print('{} 下载完成!'.format(url))def download_all_videos(url, path):'''下载m3u8文件以及多线程下载ts文件:param url::param path::return:'''# 请求m3u8文件进行下载resp = requests.get(url, headers=headers)with open("first.m3u8", mode="w", encoding="utf-8") as f:f.write(resp.text)if not os.path.exists(path):os.mkdir(path)# 开启线程 准备下载pool = ThreadPoolExecutor(max_workers=50)# 1. 读取文件tasks = []i = 0with open("first.m3u8", mode="r", encoding="utf-8") as f:for line in f:# 如果不是url 则走下次循环if line.startswith("#"):continueprint(line, i)# 开启线程tasks.append(pool.submit(down_video, line.strip(), i))i += 1print(i)# 统一等待wait(tasks)# 处理m3u8文件中的url问题
def do_m3u8_url(path, m3u8_filename="index.m3u8"):# 这里还没处理key的问题if not os.path.exists(path):os.mkdir(path)# else:# shutil.rmtree(path)# os.mkdir(path)with open(m3u8_filename, mode="r", encoding="utf-8") as f:data = f.readlines()fw = open(os.path.join(path, m3u8_filename), 'w', encoding="utf-8")abs_path = os.getcwd()i = 0for line in data:# 如果不是url 则走下次循环if line.startswith("#"):# 判断处理是存在需要秘钥fw.write(line)else:fw.write(f'{abs_path}/{path}/{i}.ts\n')i += 1def merge(filePath, filename='output'):'''进行ts文件合并 解决视频音频不同步的问题 建议使用这种:param filePath::return:'''os.chdir(path)cmd = f'ffmpeg -i index.m3u8 -c copy {filename}.mp4'os.system(cmd)if __name__ == '__main__':# 抓取99美剧闪电侠# ts文件存储目录path = 'ts'url = 'https://new.qqaku.com/20211124/nLwncbZW/1100kb/hls/index.m3u8'# 下载m3u8文件以及ts文件download_all_videos(url, path)do_m3u8_url(path)# 文件合并merge(path, 'ts2')print('over')

注意:当前视频合并所用的工具为ffmpeg 如需安装 查看我的另外一篇博客ffmpeg的使用

3.3 合并获取上面俩个代码段的代码

import re
from urllib.parse import urljoin
import requests
import os  # 执行cmd/控制台上的命令
from concurrent.futures import ThreadPoolExecutor, wait
from retrying import retrydef get_m3u8_url(url):'''获取页面中m3u8的url:param url: 电影页面的url:return:'''session = requests.Session()# 访问首页获取cookiesession.get('https://www.9meiju.cc/', headers=headers)# url = 'https://www.9meiju.cc/mohuankehuan/shandianxiadibaji/1-2.html'response = session.get(url, headers=headers)response.encoding = 'UTF-8'data = response.text# print(data)m3u8_uri = re.search('"url":"(.+?index.m3u8)"', data).group(1).replace('\\', '')# 写入文件 分析当前的页面源代码# with open('99.html', 'w', encoding='UTF-8') as f:# 写入response.content bytes二进制类型# f.write(response.content.decode('UTF-8'))# 请求可以获取index.m3u8文件response = session.get(m3u8_uri, headers=headers)# with open('m3u8_uri.text', 'w', encoding='UTF-8') as f:# 写入response.content bytes二进制类型# f.write(response.content.decode('UTF-8'))response.encoding = 'UTF-8'data = response.text# 拆分返回的内容获取真整的index.m3u8文件的url# 注意 一定要stripurl = data.split('/', 3)[-1].strip()print(data)print('m3u8_uri', m3u8_uri)url = urljoin(m3u8_uri, url)print('url', url)return url@retry(stop_max_attempt_number=3)
def down_video(url, i):'''下载ts文件:param url::param i::return:'''# print(url)# 下载ts文件# try:resp = requests.get(url, headers=headers)with open(os.path.join(path, str(i)+'.ts'), mode="wb") as f3:f3.write(resp.content)assert resp.status_code == 200def download_all_videos(url, path):'''下载m3u8文件以及多线程下载ts文件:param url::param path::return:'''# 请求m3u8文件进行下载resp = requests.get(url, headers=headers)with open("index.m3u8", mode="w", encoding="utf-8") as f:f.write(resp.content.decode('UTF-8'))if not os.path.exists(path):os.mkdir(path)# 开启线程 准备下载pool = ThreadPoolExecutor(max_workers=50)# 1. 读取文件tasks = []i = 0with open("index.m3u8", mode="r", encoding="utf-8") as f:for line in f:# 如果不是url 则走下次循环if line.startswith("#"):continueprint(line, i)# 开启线程tasks.append(pool.submit(down_video, line.strip(), i))i += 1print(i)# 统一等待wait(tasks)# 如果阻塞可以给一个超时参数# wait(tasks, timeout=1800)def do_m3u8_url(path, m3u8_filename="index.m3u8"):# 这里还没处理key的问题if not os.path.exists(path):os.mkdir(path)# else:# shutil.rmtree(path)# os.mkdir(path)with open(m3u8_filename, mode="r", encoding="utf-8") as f:data = f.readlines()fw = open(os.path.join(path, m3u8_filename), 'w', encoding="utf-8")abs_path = os.getcwd()i = 0for line in data:# 如果不是url 则走下次循环if line.startswith("#"):fw.write(line)else:fw.write(f'{abs_path}/{path}/{i}.ts\n')i += 1def merge(path, filename='output'):'''进行ts文件合并 解决视频音频不同步的问题 建议使用这种:param filePath::return:'''os.chdir(path)cmd = f'ffmpeg -i index.m3u8 -c copy {filename}.mp4'os.system(cmd)if __name__ == '__main__':headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}# 电影的url 返回index.m3u8的url地址url = get_m3u8_url('https://www.9meiju.cc/mohuankehuan/shandianxiadibaji/1-2.html')# ts文件存储目录path = 'ts'# 下载m3u8文件以及ts文件download_all_videos(url, path)do_m3u8_url(path)# 文件合并merge(path, '第二集')print('over')

4、注意事项

4.1 说明

在获取index.m3u8文件的内容时,有的文件内容会显示…jpg/png的情况,并没显示…ts,那么遇到这种情况需要单独处理 内容如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这种情况使用上面的代码就无法进行正常合并,合并后的视频无法播放

但使用ffprobe分析,发现识别为png,进而导致无法正常拼接

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这种情况下,只需要将其中PNG文件头部分全部使用FF填充,即可处理该问题

填充后的效果如图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.2 使用代码进行处理

# 解析伪装成png的ts
def resolve_ts(src_path, dst_path):'''如果m3u8返回的ts文件地址为https://p1.eckwai.com/ufile/adsocial/7ead0935-dd4f-4d2f-b17d-dd9902f8cc77.png则需要下面处理后 才能进行合并原因在于 使用Hexeditor打开后,发现文件头被描述为了PNG在这种情况下,只需要将其中PNG文件头部分全部使用FF填充,即可处理该问题:return:'''if not os.path.exists(dst_path):os.mkdir(dst_path)file_list = sorted(os.listdir(src_path), key=lambda x: int(x.split('.')[0]))for i in file_list:origin_ts = os.path.join(src_path, i)resolved_ts = os.path.join(dst_path, i)try:infile = open(origin_ts, "rb")  # 打开文件outfile = open(resolved_ts, "wb")  # 内容输出data = infile.read()outfile.write(data)outfile.seek(0x00)outfile.write(b'\xff\xff\xff\xff')outfile.flush()infile.close()  # 文件关闭outfile.close()except:passprint('resolve ' + origin_ts + ' success')

4.3 完整代码

import shutil
import time
from urllib.parse import urljoinimport requests
import os
import re
from concurrent.futures import ThreadPoolExecutor, waitdef get_m3u8_url(url):'''获取页面中m3u8的url:param url: 电影页面的url:return:'''session = requests.Session()# 访问首页获取cookiesession.get('https://www.9meiju.cc/', headers=headers)# url = 'https://www.9meiju.cc/mohuankehuan/shandianxiadibaji/1-2.html'response = session.get(url, headers=headers)response.encoding = 'UTF-8'data = response.text# print(data)m3u8_uri = re.search('"url":"(.+?index.m3u8)"', data).group(1).replace('\\', '')# 请求可以获取index.m3u8文件response = session.get(m3u8_uri, headers=headers)response.encoding = 'UTF-8'data = response.text# 拆分返回的内容获取真整的index.m3u8文件的url# 注意 一定要stripurl = data.split('/', 3)[-1].strip()print(data)print('m3u8_uri', m3u8_uri)url = urljoin(m3u8_uri, url)print('url', url)return urldef down_video(url, i):'''下载ts文件:param url::param i::return:'''# print(url)# 下载ts文件resp = requests.get(url, headers=headers)with open(os.path.join(path, str(i)+'.ts'), mode="wb") as f3:f3.write(resp.content)# print('{} 下载完成!'.format(url))def download_all_videos(url, path):'''下载m3u8文件以及多线程下载ts文件:param url::param path::return:'''# 请求m3u8文件进行下载resp = requests.get(url, headers=headers)with open("index.m3u8", mode="w", encoding="utf-8") as f:f.write(resp.content.decode('UTF-8'))if not os.path.exists(path):os.mkdir(path)# 开启线程 准备下载pool = ThreadPoolExecutor(max_workers=50)# 1. 读取文件tasks = []i = 0with open("index.m3u8", mode="r", encoding="utf-8") as f:for line in f:# 如果不是url 则走下次循环if line.startswith("#"):continueprint(line, i)# 开启线程tasks.append(pool.submit(down_video, line.strip(), i))i += 1print(i)# 统一等待wait(tasks)# 解析伪装成png的ts
def resolve_ts(src_path, dst_path):'''如果m3u8返回的ts文件地址为https://p1.eckwai.com/ufile/adsocial/7ead0935-dd4f-4d2f-b17d-dd9902f8cc77.png则需要下面处理后 才能进行合并原因在于 使用Hexeditor打开后,发现文件头被描述为了PNG在这种情况下,只需要将其中PNG文件头部分全部使用FF填充,即可处理该问题:return:'''if not os.path.exists(dst_path):os.mkdir(dst_path)file_list = sorted(os.listdir(src_path), key=lambda x: int(x.split('.')[0]))for i in file_list:origin_ts = os.path.join(src_path, i)resolved_ts = os.path.join(dst_path, i)try:infile = open(origin_ts, "rb")  # 打开文件outfile = open(resolved_ts, "wb")  # 内容输出data = infile.read()outfile.write(data)outfile.seek(0x00)outfile.write(b'\xff\xff\xff\xff')outfile.flush()infile.close()  # 文件关闭outfile.close()except:pass"""else:# 删除目录shutil.rmtree(src_path)# 将副本重命名为正式文件os.rename(dst_path, dst_path.rstrip('2'))"""print('resolve ' + origin_ts + ' success')# 处理m3u8文件中的url问题
def do_m3u8_url(path, m3u8_filename="index.m3u8"):# 这里还没处理key的问题if not os.path.exists(path):os.mkdir(path)with open(m3u8_filename, mode="r", encoding="utf-8") as f:data = f.readlines()fw = open(os.path.join(path, m3u8_filename), 'w', encoding="utf-8")abs_path = os.getcwd()i = 0for line in data:# 如果不是url 则走下次循环if line.startswith("#"):fw.write(line)else:fw.write(f'{abs_path}/{path}/{i}.ts\n')i += 1def merge(path, filename='output'):'''进行ts文件合并 解决视频音频不同步的问题 建议使用这种:param filePath::return:'''os.chdir(path)cmd = f'ffmpeg -i index.m3u8 -c copy {filename}.mp4'os.system(cmd)if __name__ == '__main__':headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36"}url = get_m3u8_url('https://www.9meiju.cc/mohuankehuan/shandianxiadibaji/1-20.html')# 抓取99美剧闪电侠# ts文件存储目录path = 'ts'# 下载m3u8文件以及ts文件download_all_videos(url, path)# 合并png的ts文件src_path = pathdst_path = path+'2'resolve_ts(src_path, dst_path)do_m3u8_url(dst_path)merge(dst_path, '闪电侠')print('over')

5、解密处理

  • 上面我们讲的是没有经过加密的 ts 文件,这些文件下载后直接可以播放,但经过AES-128加密后的文件下载后会无法播放,所以还需要进行解密。

  • 如何判断是否需要加密?观察视频网站是否有m3u8的文件传输,下载下来并打开:

    无需解密index.m3u8文件

    #EXTM3U
    #EXT-X-VERSION:3
    #EXT-X-TARGETDURATION:4
    #EXT-X-PLAYLIST-TYPE:VOD
    #EXT-X-MEDIA-SEQUENCE:0
    #EXTINF:3.086,
    https://hey05.cjkypo.com/20211215/FMbNtNzz/1100kb/hls/7qs6gJc0.ts
    #EXTINF:2.085,
    https://hey05.cjkypo.com/20211215/FMbNtNzz/1100kb/hls/rYpHhq0I.ts
    #EXTINF:2.085,
    https://hey05.cjkypo.com/20211215/FMbNtNzz/1100kb/hls/bfays5sw.ts
    

    需要解密index.m3u8文件

    #EXT-X-VERSION:3
    #EXT-X-TARGETDURATION:1
    #EXT-X-PLAYLIST-TYPE:VOD
    #EXT-X-MEDIA-SEQUENCE:0
    #EXT-X-KEY:METHOD=AES-128,URI="/20220418/671fJxOB/2000kb/hls/key.key" # 当前路径为解密秘钥的位置  需要使用代码拼凑成完整路径 进行请求 域名+/20220418/671fJxOB/2000kb/hls/key.key
    #EXTINF:1.235,
    /20220418/671fJxOB/2000kb/hls/kj6uqHoP.ts  # 并且这里ts的url也要拼凑完整
    #EXTINF:1.001,
    /20220418/671fJxOB/2000kb/hls/ZXX8LYPa.ts
    #EXTINF:1.001,
    /20220418/671fJxOB/2000kb/hls/sOezpD2H.ts
    #EXTINF:1.001,
    ...
    
  • 如果你的文件是加密的,那么你还需要一个key文件,Key文件下载的方法和m3u8文件类似,如下所示 key.key 就是我们需要下载的 key 文件,并注意这里 m3u8 有2个,需要使用的是像上面一样存在 ts 文件超链接的 m3u8 文件

  • 下载所有 ts 文件,将下载好的所有的 ts 文件、m3u8、key.key 放到一个文件夹中,将 m3u8 文件改名为 index.m3u8,将 key.key 改名为 key.m3u8 。更改 index.m3u8 里的 URL,变为你本地路径的 key 文件,将所有 ts 也改为你本地的路径

    文件路径

    project/

    ​ ts/

    ​ 0.ts

    ​ 1.ts

    ​ …

    ​ index.m3u8

    ​ key.m3u8

    修改后的index.m3u8内容如下所示:

    #EXTM3U
    #EXT-X-VERSION:3
    #EXT-X-TARGETDURATION:1
    #EXT-X-PLAYLIST-TYPE:VOD
    #EXT-X-MEDIA-SEQUENCE:0
    #EXT-X-KEY:METHOD=AES-128,URI="/Users/xialigang/PycharmProjects/爬虫/抓取带秘钥的电影/ts/key.m3u8"
    #EXTINF:1.235,
    /Users/xialigang/PycharmProjects/爬虫/抓取带秘钥的电影/ts/0.ts
    #EXTINF:1.001,
    /Users/xialigang/PycharmProjects/爬虫/抓取带秘钥的电影/ts/1.ts
    #EXTINF:1.001,
    /Users/xialigang/PycharmProjects/爬虫/抓取带秘钥的电影/ts/2.ts
    

    处理index.m3u8内容的代码如下所示

    import time
    from urllib.parse import urljoinimport requests
    import os
    from concurrent.futures import ThreadPoolExecutor, wait
    import reheaders = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36"
    }
    

    def down_video(url, i):
    ‘’’
    下载ts文件
    :param url:
    :param i:
    :return:
    ‘’’
    # print(url)
    # 下载ts文件
    resp = requests.get(url, headers=headers)
    with open(os.path.join(path, str(i) + ‘.ts’), mode=“wb”) as f3:
    f3.write(resp.content)
    # print(‘{} 下载完成!’.format(url))

    def download_all_videos(path, host):
    ‘’’
    下载m3u8文件以及多线程下载ts文件
    :param url:
    :param path:
    :return:
    ‘’’
    if not os.path.exists(path):
    os.mkdir(path)
    # 开启线程 准备下载
    pool = ThreadPoolExecutor(max_workers=50)
    # 1. 读取文件
    tasks = []
    i = 0
    with open(“index.m3u8”, mode=“r”, encoding=“utf-8”) as f:
    for line in f:
    # 如果不是url 则走下次循环
    if line.startswith(“#”):
    continue
    line = host + line
    print(line, i)
    # 开启线程
    tasks.append(pool.submit(down_video, line.strip(), i))
    i += 1
    # 统一等待
    wait(tasks)

    处理m3u8文件中的url问题

    def do_m3u8_url(url, path, m3u8_filename=“index.m3u8”):
    # 这里还没处理key的问题
    if not os.path.exists(path):
    os.mkdir(path)

    with open(m3u8_filename, mode="r", encoding="utf-8") as f:data = f.readlines()fw = open(os.path.join(path, m3u8_filename), 'w')
    abs_path = os.getcwd()
    i = 0
    for line in data:# 如果不是url 则走下次循环if line.startswith("#"):# 判断处理是存在需要秘钥if line.find('URI') != -1:line = re.sub('(#EXT-X-KEY:METHOD=AES-128,URI=")(.*?)"', f'\\1{os.path.join(abs_path, path)}/key.m3u8"',line)host = url.rsplit('/', 1)[0]# 爬取keydownload_m3u8(host + '/key.key', os.path.join(path, 'key.m3u8'))fw.write(line)else:fw.write(f'{abs_path}/{path}/{i}.ts\n')i += 1
    

    def download_m3u8(url, m3u8_filename=“index.m3u8”, state=0):
    print(‘正在下载index.m3u8文件’)
    resp = requests.get(url, headers=headers)
    with open(m3u8_filename, mode=“w”, encoding=“utf-8”) as f:
    f.write(resp.text)

    def merge(filePath, filename=‘output’):
    ‘’’
    进行ts文件合并 解决视频音频不同步的问题 建议使用这种
    :param filePath:
    :return:
    ‘’’
    os.chdir(path)
    cmd = f’ffmpeg -i index.m3u8 -c copy {filename}.mp4’
    os.system(cmd)

    def get_m3u8_data(first_m3u8_url):
    session = requests.Session()

    # 请求第一次m3u8de url
    resp = session.get(first_m3u8_url, headers=headers)
    resp.encoding = 'UTF-8'
    data = resp.text# 第二次请求m3u8文件地址 返回最终包含所有ts文件的m3u8
    second_m3u8_url = urljoin(first_m3u8_url, data.split('/', 3)[-1].strip())
    resp = session.get(second_m3u8_url, headers=headers)
    with open('index.m3u8', 'wb') as f:f.write(resp.content)
    return second_m3u8_url
    

    if name == ‘main’:
    # ts文件存储目录
    path = ‘ts’
    # 带加密的ts文件的 index.m3u8 url
    url = ‘https://s7.fsvod1.com/20220622/5LnZiDXn/index.m3u8’
    meu8_url = get_m3u8_data(url)
    # 下载m3u8文件以及ts文件
    host = ‘https://s7.fsvod1.com’ # 主机地址 用于拼凑完整的ts路径和秘钥路径
    download_all_videos(path, host)
    do_m3u8_url(meu8_url, path)

    # 文件合并
    merge(path, '奇异博士')
    print('over')
    
  • 这样就大功告成了!我们成功解密并使用 ffmpeg 合并了这些 ts 视频片段,实际应用场景可能和这不一样,具体网站具体分析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/6276.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

html语法

网站是指在因特网上根据一定规则&#xff0c;使用html等制作的用于展示特定内容相关的网页集合 网站由很多网页组成&#xff0c;网页是构成网站的基本元素&#xff0c;通常由图片、连接、视频、声音、文字等元素组成&#xff0c;一般用.htm和.html做后缀&#xff0c;又被称为h…

WPF使用Prism框架首页界面

1. 首先确保已经下载了NuGet包MaterialDesignThemes 2.我们通过包的项目URL可以跳转到Github上查看源码 3.找到首页所在的代码位置 4.将代码复制下来&#xff0c;删除掉自己不需要的东西&#xff0c;最终如下 <materialDesign:DialogHostDialogTheme"Inherit"Ide…

[ DOS 命令基础 3 ] DOS 命令详解-文件操作相关命令

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

WPF+MVVM案例实战(二十)- 制作一个雷达辐射效果的按钮

文章目录 1、案例效果2、文件创建与代码实现1、创建文件2、图标资源文件3、源代码获取1、案例效果 2、文件创建与代码实现 1、创建文件 打开 Wpf_Examples 项目,在 Views 文件夹下创建窗体界面 RadarEffactWindow.xaml 。代码功能分两个部分完成,一个是样式,一个是动画。页…

git中使用tag(标签)的方法及重要性

在Git中打标签&#xff08;tag&#xff09;通常用于标记发布版本或其他重要提交。 Git中打标签的步骤&#xff1a; 列出当前所有的标签 git tag创建一个指向特定提交的标签 git tag <tagname> <commit-hash>创建一个带注释的标签&#xff0c;通常用于发布版本 git…

让火患无处遁形,RFID智能应急消防管理来帮忙

我国常受自然灾害侵扰&#xff0c;灾害间的相互影响日益加剧&#xff0c;给灾害救援任务带来了前所未有的挑战。当前&#xff0c;专业救援队伍的实力亟需扩充&#xff0c;现代救援装备的配置亟须加强&#xff0c;保障体系亟待优化&#xff0c;应急预案及联动作战机制亦需深化完…

新视野大学英语读写教程1第四版PDF+答案+听力音频

《新视野大学英语》(第四版) 系列教材包含1—4级&#xff0c; 供两个学年使用。每一级别包含《读写教程》(配教师用书)、《视听说教程》(配教师用书)、《综合训练》和《长篇阅读》。教材提供教学管理平台、数字课程、微课视频、移动学习应用、教学课件、试题库等立体丰富的教学…

华为手机卸载系统应用的方法

摘要&#xff1a; 1.手机环境&#xff1a;手机需要开启开发者模式并使用usb连接电脑&#xff0c;并选择文件传输模式 2.电脑环境&#xff1a;使用鸿蒙工具箱进行傻瓜操作或安装adb工具进行命令卸载 3.鸿蒙工具箱和adb工具本质都是使用adb shell pm uninstall -k --user 0 xx…

优化EDM邮件营销,送达率与用户体验双赢

EDM邮件营销需选对平台&#xff0c;优化邮件列表&#xff0c;确保内容优质&#xff0c;进行邮件测试&#xff0c;关注用户反馈调整频率&#xff0c;以保高送达率&#xff0c;提升营销效果。 1. 了解电子邮件送达率的重要性 在开始优化邮件送达率之前&#xff0c;首先需要理解电…

class com.alibaba.fastjson2.JSONObject cannot be cast to class com.ruoyi.sys

class com.alibaba.fastjson2.JSONObject cannot be cast to class com.ruoyi.sys ry-cloud报错原因解决 ry-cloud 报错 系统监控→在线用户打开后报错 报错信息如下 class com.alibaba.fastjson2.JSONObject cannot be cast to class com.ruoyi.sys原因 type导致&#xff…

靠Python真的能实现经济自由,学会了你也可以

不知道大家有没有注意到&#xff0c;最近关注的很多人都在聊“副业and兼职”这件事。 毕竟单一收入已经不能满足现代人的需求了。 对于普通人来说&#xff0c;想要跳出固定思维和舒适圈&#xff0c;相比于孤注一掷的创业&#xff0c;更推荐兼职。 很多人想要创业&#xff0c;…

掌握 PyQt5:从零开始的桌面应用开发

PyQT5——图形化界面 文章目录 PyQT5——图形化界面集成化图形界面工具为什么使用 \$ProjectFileDir$?示例场景其他 Varaiablespyuic参数解释整体含义示例使用PyQt5和pyuic 创建pyqt5的程序创建一个窗口app.exec\_()和sys.exit(app.exec_())的区别1. app.exec_()2. sys.exit(a…

[HCTF 2018]WarmUp 1

[HCTF 2018]WarmUp 1 审题 观察题目&#xff0c;查看源代码&#xff0c;看到source.php。 访问&#xff0c;看到源代码。 知识点 PHP的代码审计&#xff0c;include函数的应用&#xff0c;文件包含漏洞。 代码审计 <?phphighlight_file(__FILE__);class emmm{public s…

智慧水肥一体化:道品科技现代农业的智能管理模式

智慧水肥一体化是现代农业中一种重要的管理模式&#xff0c;它通过信息技术和物联网技术的结合&#xff0c;实现对水资源和肥料的智能化管理。这一系统的主要功能包括环境监测、集中管理、智能控制、主动报警和数据管理。以下将分别对这些功能进行详细阐述&#xff0c;并探讨智…

UE5.4 PCG 岩石批量复制创建顶部植被

1.复制石头和石头的采点 2.加入想要的植被

卖模版还能赚到钱吗?

说到赚钱&#xff0c;我想大部分人都会感兴趣。但如果告诉大家现阶段卖模板也能赚钱&#xff0c;可能还是有人不信。我要说说我的观察了。 本文可在公众号「德育处主任」免费阅读 我是一只临期程序猿&#xff0c;我最早接触到“模板能卖钱”这个概念是在模板王里。模板王平台上…

怎么样鉴定疾病相关稀有细胞群?二值化精细模型标签,这个刚发的顶刊单细胞算法值得一学!

生信碱移 HiDDEN&#xff1a;抽丝剥茧 在具有病例和对照单细胞RNA测序研究中&#xff0c;样本级标签通常被直接赋予单个细胞&#xff0c;假设所有病例细胞都受影响。这种传统方法在受影响细胞比例较小或扰动强度较弱时&#xff0c;难以有效识别关键细胞及其标记基因&#xff…

第十九周机器学习笔记:GAN的数学理论知识与实际应用的操作

第十九周周报 摘要Abstratc一、机器学习——GAN Basic Theory1. Maximum Likelihood Estimation2. 复习训练GAN的过程3. Objective function与JS散度相关性推导4. GAN的实际做法 总结 摘要 本周周报主要围绕生成对抗网络&#xff08;GAN&#xff09;的基础知识和理论进行深入探…

计算机网络八股文个人总结

1.TCP/IP模型和OSI模型的区别 在计算机网络中&#xff0c;TCP/IP 模型和 OSI 模型是两个重要的网络协议模型。它们帮助我们理解计算机通信的工作原理。以下是它们的主要区别&#xff0c;以通俗易懂的方式进行解释&#xff1a; 1. 模型层数 OSI 模型&#xff1a;有 7 层&#…

Web Workers 学习笔记

最近在开发中遇到了一个需求&#xff0c;一大堆的图片都需要调用两个接口。这对单线程的 JavaScript 运行环境构成了挑战&#xff0c;容易影响用户体验。所以决定学习 Web Workers 并记录一下。 Web Workers 的作用就是提供一个多线程环境&#xff0c;允许将一些繁重任务&…