1 #-*- coding:utf-8 -*-
2 importos3 importsys4 importrequests5 importdatetime6 from Crypto.Cipher importAES7 from binascii importb2a_hex, a2b_hex8
9 #reload(sys)
10 #sys.setdefaultencoding('utf-8')
11
12 if 1:13 defdebug(s):14 print(s)15 else:16 defdebug(s):17 pass
18
19 importimportlib20 importlib.reload(sys)21
22 def download(url, savefile_path=''):23 #创建download目录
24 download_path = os.getcwd() + "\download"
25 if notos.path.exists(download_path):26 os.mkdir(download_path)27
28 #新建日期文件夹,如果没有指定文件存储位置,就用年月日创建文件夹,否则用指定的文件夹
29 if notsavefile_path:30 savefile_path = os.path.join(download_path, datetime.datetime.now().strftime('%Y%m%d'))31 else:32 savefile_path =os.path.join(download_path, savefile_path)33 print("savefile_path =" +savefile_path)34 if notos.path.exists(savefile_path):35 os.mkdir(savefile_path)36
37
38 #如果不存在first.m3u8,就重新获取,并保存,否则证明之前已经获取过,直接读取就行了
39 if not os.path.exists(os.path.join(download_path,'first.m3u8')):40 all_content = requests.get(url).text #获取第一层M3U8文件内容
41 with open( os.path.join(download_path,'first.m3u8'),'w') as f:42 f.write(all_content)43 print("save first.m3u8")44 else:45 print("first.m3u8 is exist,just read it")46 all_content = open( os.path.join(download_path,'first.m3u8'),'r').read()47
48 #不是M3U8文件,直接报错退出
49 if "#EXTM3U" not inall_content:50 raise BaseException("非M3U8的链接")51 #
52 if "EXT-X-STREAM-INF" in all_content: #第一层
53 #从第一层中读取所有的文件组成行列表 file_line
54 print("we need to get the second line")55 file_line = all_content.split("\n")56 #找到 .m3u8 ,拼出第二层的链接
57 for line infile_line:58 if '.m3u8' inline:59 url = url.rsplit("/", 1)[0] + "/" + line #拼出第二层m3u8的URL
60 print("second line url =" +url)61 #没存,就存一下,同first.m3u8的逻辑
62 if not os.path.exists(os.path.join(download_path,'second.m3u8')):63 all_content =requests.get(url).text64 with open( os.path.join(download_path,'second.m3u8'),'w') as f:65 f.write(all_content)66 print("second.m3u8 has been saved")67 else:68 all_content = open( os.path.join(download_path,'second.m3u8'),'r').read()69 break
70 #到此为止,all_content里面的内容已经更新成了包含所有文件名的最终文件
71 #url 更新成了下载最终m3u8的URL
72
73 #把里面的元素分割出来
74 file_line = all_content.split("\n")75
76 unknow =True77 key = ""
78
79 for line infile_line:80 #先找到解密key
81 if "#EXT-X-KEY" in line: #找解密Key
82 method_pos = line.find("METHOD")83 comma_pos = line.find(",")84 method = line[method_pos:comma_pos].split('=')[1]85 print("Decode Method:", method)86
87 uri_pos = line.find("URI")88 quotation_mark_pos = line.rfind('"')89 key_path = line[uri_pos:quotation_mark_pos].split('"')[1]90
91 key_url = url.rsplit("/", 1)[0] + "/" + key_path #拼出key解密密钥URL
92 res =requests.get(key_url)93 key =res.content94
95 with open( os.path.join(download_path,'key.key'),'wb') as f:96 f.write(key)97
98 cryptor =AES.new(key, AES.MODE_CBC, key)99 print( "key:", key)100 break
101 print("you cann't see me")102 #再进行下载和解密
103 for index, line in enumerate(file_line): #第二层
104 if "EXTINF" in line: #找ts地址并下载
105 unknow =False106 pd_url = url.rsplit("/", 1)[0] + "/" + file_line[index + 1] #拼出ts片段的URL
107
108 c_fule_name = file_line[index + 1].rsplit("/", 1)[-1]109 #如果文件已经存在,就下一个
110 ifos.path.exists( os.path.join(savefile_path, c_fule_name) ):111 print("file %s exist, next" %c_fule_name)112 continue
113 #网络不好的时候会失败,所以重复3次
114 for i in range(3):115 #获取视频内容
116 print("get video" + datetime.datetime.now().strftime('%H:%M:%S'))117 res =requests.get(pd_url)118 try:119 if len(key): #AES 解密,有key就是需要解密
120 with open(os.path.join(savefile_path, c_fule_name), 'ab') as f:121 f.write(cryptor.decrypt(res.content))122 print(c_fule_name + "success")123 break
124 else: #没有key就不需要解密了,直接保存文件就行了
125 with open(os.path.join(savefile_path, c_fule_name), 'ab') as f:126 f.write(res.content)127 f.flush()128 print(c_fule_name + "success")129 break
130 except: #网络不好导致下载失败,清除文件
131 print( str(i+1) + "download error, file:" +c_fule_name)132 os.remove(os.path.join(savefile_path, c_fule_name))133 else: #下载失败,先跳过这个文件,后面重新执行的时候在重新下载
134 print("download file has failed 3 times, jump it")135 #exit()
136
137 ifunknow:138 raise BaseException("未找到对应的下载链接")139 else:140 print( "下载完成")141 #merge_file(savefile_path)
142
143 defmerge_file(path):144 os.chdir(path)145 cmd = "copy /b * new.ts"
146 #os.system(cmd)
147 #os.system('del /Q *.ts')
148 #os.system('del /Q *.mp4')
149 #os.rename("new.tmp", "new.mp4")
150
151 if __name__ == '__main__':152 url = input("please input the url of index.m3u8 file:\n")153 savefile_path = input("give me a dir name to save all the video:\n(or you can just press Enter and I will create one for you)\n")154 #url = r''
155 #savefile_path = r''
156 download(url,savefile_path)