最近看到某有色網站的視頻不錯,可是這個網站的網速不太理想,就想下載看,偏偏視頻又是加密的,遂破解之。
# -*- 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()