最近看到某有色网站的视频不错,可是这个网站的网速不太理想,就想下载看,偏偏视频又是加密的,遂破解之。
# -*- coding: utf-8 -*- """ Created on 2022-03-21 0021 21:45 @Software : PyCharm @author: Administrator """ import requests, os, pyperclip, re from tqdm import tqdm path = r'E:\pojie' headers = { 'Connection': 'keep-alive', '其他header': '信息隐藏', } proxy = { 'http': None, 'https': None } def get_res(url, file_path): """ 下载ts视频流 :param url: ts流链接 :param file_path: 临时文件路径 :param key: 加密密钥 """ try: response = requests.get(url=url, timeout=120, headers=headers) with open(file_path, 'wb+') as f: f.write(response.content) except Exception as e: print(e) def get_list(url): response = requests.get(url, headers=headers, proxies=proxy) return response def get_keys(url): """ 获取加密密钥 :param url: 密钥网址 :return: """ response = requests.get(url, proxies=proxy) return response def write_keys(response, filename): """ 写入密钥文件 :param response: 返回的密钥响应 :param filename: 密钥文件名 :return: """ file_path = os.path.join(path, filename) # print(file_path) with open(file_path, 'wb+') as fp: fp.write(response.content) def get_links_from_file(path): """ 从文件中批量读取网址 :param path: 文件所在位置 :return: """ with open(path, 'r', encoding='utf-8') as fp: st = fp.readlines() return st def write_list(list_path1, list_path2, keystring): """ 重写本地m3u8文件,用于ffmpeg合成用 :param list_path1: :param list_path2: :param keystring: 记录密钥信息的那一行的字符串, 例如''#EXT-X-KEY:METHOD=AES-128,URI="E:/pojie/videokey",IV=0x00000000000000000000000000000000\n' :return: 不返回信息 """ fp1 = open(list_path1, 'r', encoding='utf-8') fp2 = open(list_path2, 'w+', encoding='utf-8') st_list = fp1.readlines() fp1.close() index = 0 for st in st_list: if st[:10] == '#EXT-X-KEY': if index < 1: fp2.write(keystring) continue elif st[:1] == "#": fp2.write(st) else: if index < 9: filename = f'00{index + 1}.ts' elif index < 99: filename = f'0{index + 1}.ts' else: filename = f'{index + 1}.ts' fp2.write(filename + '\n') index += 1 fp2.close() def get_key_url(path): """ 从下载好的m3u8文件里读取密钥网址 :param path: :return: """ with open(path, 'r') as f: st = f.read() ur = re.findall('#EXT-X-KEY:METHOD=AES-128,URI="(.*?)"', st) url = ur[0] # print(url) return url def write_video(response, filename): """ 下载视频 :param response: response响应 :param filename: 视频保存的文件名 :return: """ video_path = os.path.join(path, filename) if not os.path.exists(path): os.mkdir(path) with open(video_path, 'wb+') as fp: fp.write(response.content) def join_video(listname, newfilename): """ 利用ffmpeg合并加密的ts文件 :param listname: 本地m3u8文件路径 :param newfilename: 待合成的文件名称 :return: """ command = f'ffmpeg -allowed_extensions ALL -i {listname} -c copy {newfilename}' command1 = 'cd /d E:/pojie' print(command) os.system(command1) os.system(command) def d_k(path): """ 下载密钥 :return: """ filename = 'videokey' url = get_key_url(path) res = get_keys(url) write_keys(res, filename) return res def d_l(url): """ 下载m3u8列表 :return: """ filename = '01.m3u8' res = get_list(url) write_video(res, filename) def d_v(url_left, list_path, key): """ 下载视频 :return: """ url_list = get_links_from_file(list_path) index = 0 for url in url_list: if url[:1] == 'v': if index < 9: filename = f'00{index + 1}.ts' elif index < 99: filename = f'0{index + 1}.ts' else: filename = f'{index + 1}.ts' new_url = url_left + url new_url = new_url.strip() file_path = os.path.join(path, filename) downloadFile(new_url, file_path) # time.sleep(2) index += 1 else: continue def get_url_left(url): """ 读取m3u8的网址前缀 :param url: :return: """ url_list = url.split('/') url_list[1] = 'https:/' new_url = '/'.join(url_list[1:-1]) new_url = new_url + '/' return new_url def rename(): """ 重命名合成后的文件 :return: """ txt_path = r'C:\Users\rabbit\PycharmProjects\utils\video\links.txt' fp = open(txt_path, 'r', encoding='utf-8') st_list = fp.readlines() fp.close() path1 = r'E:\pojie' old_path = r"E:\pojie\03.mp4" filename = st_list[0].strip() + '.mp4' new_path = os.path.join(path1, filename) os.rename(old_path, new_path) fo = open(txt_path, 'w', encoding='utf-8') for index, line in enumerate(st_list): if index == 0: continue else: fo.write(line) fo.close() return new_path def delete_TS(): """ 永久删除下载的ts视频流分段 :return: """ path = r'E:\pojie' file_list = os.listdir(path) for file in file_list: if file[-2:] == 'ts': print(f'{file}已删除') file_path = os.path.join(path, file) os.remove(file_path) def downloadFile(url, name): """ 下载实时显示速度 :param url: :param name: :return: """ # print(url) # 用流stream的方式获取url的数据 resp = requests.get(url, stream=True, headers=headers, proxies=proxy) # 拿到文件的长度,并把total初始化为0 total = int(resp.headers.get('content-length', 0)) # 打开当前目录的fname文件(名字你来传入) # 初始化tqdm,传入总数,文件名等数据,接着就是写入,更新等操作了 with open(name, 'wb+') as file, tqdm( desc=name, total=total, unit='iB', unit_scale=True, unit_divisor=1024, ) as bar: for data in resp.iter_content(chunk_size=1024): size = file.write(data) bar.update(size) def mainone(): """ 主程序入口 :return: """ # 读取剪贴板中的m3u8链接 url = pyperclip.paste() if not os.path.exists(path): os.mkdir(path) path1 = "E:\\pojie\\01.m3u8" path2 = "E:\\pojie\\02.m3u8" keystring = '#EXT-X-KEY:METHOD=AES-128,URI="E:/pojie/videokey",IV=0x00000000000000000000000000000000\n' # 获取m3u8链接前缀,用于拼接ts网址 url_left = get_url_left(url) # 下载m3u8列表 d_l(url) # 下载密钥,保存到此文件中,E:/pojie/videokey res = d_k(path1) # 下载TS分段 d_v(url_left, path1, res.content) # 下载完分段后,重写本地的m3u8文件,方便后续使用ffmpeg合成 write_list(path1, path2, keystring) filename = 'E:\\pojie\\03.mp4' # 合并文件 join_video(path2, filename) # 读取目录文件并重命名 np = rename() # 删除TS分段 delete_TS() # 输出已下载好的文件名 print(np) if __name__ == '__main__': mainone()