python代码下载m3u8视频
代码如下:
# -*- coding: utf-8 -*- import requests import re import os import base64 from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad BLOCK_SIZE = 16 # Byte def write_file(file_path, content, attr): """ 写内容进文件 :param file_path: :param content: :param attr: :return: """ with open(file_path, attr) as f: f.write(content) def get_urls(m3u8_url): """ 获取视频url :param m3u8_url: :return: """ # 分割url为文件和路径 remote_path, file_name = os.path.split(m3u8_url) urls = [] try: res = requests.get(url=m3u8_url) url_regs = re.findall('#EXTINF:(.*?),\n(.*?)\n', res.text) # 正则提取url for url_reg in url_regs: # 判断是否完整url if 'http' not in url_reg[1]: url = remote_path + "/" + url_reg[1] urls.append(url) # print(url) else: urls.append(url_reg[1]) print('【url获取完成】') except Exception as e: print(e) print('【url获取失败】') return urls def get_key(m3u8_url): """ 获取解密密钥 :param m3u8_url: :return: """ # 分割url为文件和路径 remote_path, file_name = os.path.split(m3u8_url) key = None try: res = requests.get(url=m3u8_url) key_regs = re.findall('#EXT-X-KEY:METHOD=(.*?),URI="(.*?)"', res.text) # 正则提取解密密钥 # 判断是否完整url if 'http' not in key_regs[0][1]: key_url = remote_path + '/' + key_regs[0][1] else: key_url = key_regs[0][1] # 请求key key = requests.get(url=key_url).content print('【密钥获取完成】') except Exception as e: print(e) print('【密钥获取失败】') return key def download_video(m3u8_url, file_name): """ 下载视频 :param m3u8_url: :param file_name: :return: """ # 记录已下载的数据大小,单位Byte total = 0 try: # 获取解密密钥 key = get_key(m3u8_url) # 获取url urls = get_urls(m3u8_url) # 循环下载每个部分的视频 for url in urls: print('【正在下载 '+url+' 部分的视频】') res = requests.get(url=url) # 解密 content = aes_decrypt(key, res.content) total += len(content) # 追加进文件 write_file(file_name, content, 'ab+') print('【下载完成 ' + url + ' 部分的视频】') print('【已下载部分大小:'+str(total/1024)+' kb/'+str(total/(1024*1024))+' mb】') print('【下载完成】') except Exception as e: print(e) def aes_decrypt(key, crypt_content): """ 解密 :param key: :param crypt_content: :return: """ cryptor = AES.new(key, AES.MODE_CBC, key) pad_content = pad(crypt_content, BLOCK_SIZE) # print(len(crypt_content)) return unpad(cryptor.decrypt(crypt_content), BLOCK_SIZE) # return cryptor.decrypt(crypt_content) def aes_encrypt(key, text): """ 加密 :param key: :param text: :return: """ cryptor = AES.new(key, AES.MODE_CBC, key) return cryptor.encrypt(pad(text.encode(), BLOCK_SIZE)) # return cryptor.encrypt(text.encode()) def main(): download_video('http://1252524126.vod2.myqcloud.com/9764a7a5vodtransgzp1252524126/69f662df5285890816956396169/drm/v.f146750.m3u8', 'test.mp4') # print(get_key('https://1252524126.vod2.myqcloud.com/9764a7a5vodtransgzp1252524126/430c15b95285890816864188760/drm/v.f146750.m3u8')) if __name__ == '__main__': main()