下载解压 .ts文件

1.python exe程序
  1 from tkinter import *
  2 import time
  3 import urllib.request
  4 import http.cookiejar
  5 import urllib.error
  6 import urllib.parse
  7 import re
  8 import socket
  9 import os
 10 from pathlib import Path
 11 
 12 from Cryptodome.Cipher import AES
 13 from concurrent.futures import ThreadPoolExecutor
 14 LOG_LINE_NUM = 0
 15 
 16 class MY_GUI():
 17     # 初始化方法 构造方法
 18     def __init__(self, init_window_name):
 19         self.init_window_name=init_window_name
 20         self.playlist_url = None
 21         self.max_num = 250
 22         self.header = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
 23                        "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
 24                        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0",
 25                        "Connection": "keep-alive"}
 26         self.cjar = http.cookiejar.CookieJar()
 27         self.cookie = urllib.request.HTTPCookieProcessor(self.cjar)
 28         self.opener = urllib.request.build_opener(self.cookie)
 29         urllib.request.install_opener(self.opener)
 30 
 31         self.pool = ThreadPoolExecutor(max_workers=10)
 32         self.sum = 0
 33         # 利用socket模块,使得每次重新下载的时间变短
 34         socket.setdefaulttimeout(20)
 35 
 36     def download_file(self, url, target):
 37         # 解决下载不完全问题且避免陷入死循环
 38         try:
 39             print(END, str("下载:"+url)+'\n')
 40             # self.write_log_to_Text(str("下载:"+url))
 41             urllib.request.urlretrieve(url, target)
 42         except socket.timeout:
 43             count = 1
 44             while count <= 5:
 45                 try:
 46                     urllib.request.urlretrieve(url, target)
 47                     break
 48                 except socket.timeout:
 49                     err_info = url + ' Reloading for %d time' % count if count == 1 else 'Reloading for %d times' % count
 50                     print(END, str(err_info) + '\n')
 51                     count += 1
 52                 except:
 53                     # 解决远程主机关闭问题
 54                     self.download_file(url, target)
 55             if count > 5:
 56                 print(str('downloading fialed!'))
 57         except:
 58             # 解决远程主机关闭问题
 59             self.download_file(url, target)
 60 
 61     # 打开 m3u8
 62     def open_web(self, url):
 63         try:
 64             response = self.opener.open(url, timeout=3)
 65         except urllib.error.URLError as e:
 66             print(END, str('open ' + url + ' error') + '\n')
 67             self.write_log_to_Text(str('open ' + url + ' error'))
 68             if hasattr(e, 'code'):
 69                 print(END, str(e.code) + '\n')
 70                 self.write_log_to_Text(str(e.code))
 71             if hasattr(e, 'reason'):
 72                 print(END, str(e.reason) + '\n')
 73                 self.write_log_to_Text(str(e.reason))
 74         else:
 75             return response.read()
 76 
 77     '''第一步、解析m3u8'''
 78     def get_available_IP(self):
 79         print(END, str('开始获取真实的url') + '\n')
 80         self.write_log_to_Text(str('开始获取真实的url'))
 81         data = self.open_web(self.m3u8_url).decode('utf-8')
 82         tv_lists = re.findall(',\n(.*).ts\n', data)
 83         return tv_lists
 84 
 85     # 下载.ts
 86     def download_for_multi_process(self, ts):
 87         ts_url = ts + ".ts"
 88         str_style = "%05d" % self.sum
 89         path_str = str_style + '.ts'
 90         downUrl = self.url + ts_url
 91         downPath = self.sourceFile + path_str
 92         if os.path.isfile(downPath) and os.path.getsize(downPath) > 0:
 93             print(END, str("file already exist") + '\n')
 94             self.write_log_to_Text(str("file already exist"))
 95         else:
 96             self.download_file(downUrl, downPath)
 97         self.sum = self.sum + 1
 98 
 99     # 开始线程
100     def download_with_multi_process(self, ts_list):
101         print(END, str('开始多线程下载') + '\n')
102         self.write_log_to_Text(str("开始多线程下载"))
103         task = self.pool.map(self.download_for_multi_process, ts_list)  # 此时非阻塞
104         for t in task:  # 此时会变成阻塞
105             pass
106 
107     '''第四步、合并ts文件'''
108     def merge_ts_file_with_os(self):
109         print(END, str('开始合并') + '\n')
110         self.write_log_to_Text(str("开始合并"))
111         # 合并ts文件
112         os.chdir(self.chdir)
113         shell_str = f'copy /b *.ts {self.merge_ts_path}'
114         os.system(shell_str)
115         os.system(f'del /Q *.ts')
116         os.chdir(self.sourceFile)
117         os.system(f'del /Q *.ts')
118         os.chdir(self.chdir)
119         self.write_log_to_Text(str("合并完成"))
120         print(END, str('合并完成') + '\n')
121 
122     # 解密
123     def decodeFile(self):
124         key = self.key
125         self.chdir = self.sourceFile
126         if len(key):
127             cryptor = AES.new(key, AES.MODE_CBC, key)
128             # 读取ts文件
129             sourceFile = self.sourceFile
130             savefile_path = self.saveFile
131             list_file = os.listdir(sourceFile)
132             for file in list_file:
133                 c_fule_name = file
134                 file_line = file
135                 if ".ts" in c_fule_name:
136                     fo = open(os.path.join(sourceFile, file_line), 'rb');
137                     if len(key):  # AES 解密,有key就是需要解密
138                         with open(os.path.join(savefile_path, c_fule_name), 'ab') as f:
139                             f.write(cryptor.decrypt(fo.read()))
140             print(END, str("解密完成") + '\n')
141             self.write_log_to_Text(str("解密完成"))
142             self.chdir = self.saveFile
143         self.merge_ts_file_with_os()  # 合并ts文件
144 
145     #设置窗口
146     def set_init_window(self):
147         self.init_window_name.title("ts文件下载工具_v2.0   by: 龙林基")           #窗口名
148         self.init_window_name.geometry('500x600+10+10')
149         #标签
150         self.init_data_label = Label(self.init_window_name, text="请求数据")
151         self.init_data_label.grid(row=0, column=0)
152 
153         self.request_m3u8_label= Label(self.init_window_name, text="m3u8_url:")
154         self.request_m3u8_label.grid(row=2, column=0)
155         self.request_separator_label = Label(self.init_window_name, text="separator:")
156         self.request_separator_label.grid(row=11, column=0)
157         self.request_fileName_label = Label(self.init_window_name, text="file_name:")
158         self.request_fileName_label.grid(row=21, column=0)
159         self.request_key_label = Label(self.init_window_name, text="key:")
160         self.request_key_label.grid(row=31, column=0)
161         self.request_sourceFile_label = Label(self.init_window_name, text="sourceFile:")
162         self.request_sourceFile_label.grid(row=41, column=0)
163         self.request_saveFile_label = Label(self.init_window_name, text="saveFile:")
164         self.request_saveFile_label.grid(row=51, column=0)
165 
166         self.log_label = Label(self.init_window_name, text="日志")
167         self.log_label.grid(row=120, column=0)
168 
169 
170         #文本框
171         self.request_m3u8_Text = Text(self.init_window_name, width=50, height=1.5)  #m3u8_url录入框
172         self.request_m3u8_Text.grid(row=2, column=2, rowspan=2)
173         self.request_separator_Text = Text(self.init_window_name, width=50, height=1.5)  # separator录入框
174         self.request_separator_Text.grid(row=11, column=2, rowspan=2)
175         self.request_fileName_Text = Text(self.init_window_name, width=50, height=1.5)  # fileName录入框
176         self.request_fileName_Text.grid(row=21, column=2, rowspan=2)
177         self.request_key_Text = Text(self.init_window_name, width=50, height=1.5)  # ket录入框
178         self.request_key_Text.grid(row=31, column=2, rowspan=2)
179         self.request_sourceFile_Text = Text(self.init_window_name, width=50, height=1.5)  # sourceFile录入框
180         self.request_sourceFile_Text.grid(row=41, column=2, rowspan=2)
181         self.request_sourceFile_Text.insert(END,"D:\\soft\\python\\project\\download\\")
182         self.request_saveFile_Text = Text(self.init_window_name, width=50, height=1.5)  # saveFile录入框
183         self.request_saveFile_Text.grid(row=51, column=2, rowspan=2)
184         self.request_saveFile_Text.insert(END,"D:\\soft\\python\\project\\download\\decode\\")
185         # 按钮
186         self.submit_button = Button(self.init_window_name, text="submit", width=5,
187                                     command=self.runmain)  # 调用内部方法  加()为直接调用
188         self.submit_button.grid(row=60, column=2)
189         self.reset_button = Button(self.init_window_name, text="reset", width=5,
190                                    command=self.reset)  # 调用内部方法  加()为直接调用
191         self.reset_button.grid(row=60, column=3)
192 
193         self.log_data_Text = Text(self.init_window_name, width=66, height=30)  # 日志框
194         self.log_data_Text.grid(row=130, column=0, columnspan=20)
195 
196         # 滚动条
197         self.result_data_scrollbar_y = Scrollbar(self.init_window_name)  # 创建纵向滚动条
198         self.result_data_scrollbar_y.config(command=self.log_data_Text.yview)  # 将创建的滚动条通过command参数绑定到需要拖动的Text上
199         self.log_data_Text.config(yscrollcommand=self.result_data_scrollbar_y.set) # Text反向绑定滚动条
200         self.result_data_scrollbar_y.grid(row=130, column=23, rowspan=15, sticky='NS')
201 
202     # 主函数
203     def runmain(self):
204         m3u8s = []
205         names = []
206         keys = []
207         substr = str(self.request_separator_Text.get(1.0,END))
208         if len(str(self.request_m3u8_Text.get(1.0,END))) > 1:
209             m3u8s = str(self.request_m3u8_Text.get(1.0,END)).split(",")
210         if len(str(self.request_fileName_Text.get(1.0,END))) > 1:
211             names = str(self.request_fileName_Text.get(1.0,END)).split(",")
212         if len(str(self.request_key_Text.get(1.0,END))) > 1:
213             keys = str(self.request_key_Text.get(1.0,END)).split(",")
214         # 下载路径
215         self.sourceFile = str(self.request_sourceFile_Text.get(1.0,END)).split("\n")[0]
216         self.saveFile = str(self.request_saveFile_Text.get(1.0,END)).split("\n")[0]
217         # 判断路径是否存在
218         my_file = Path(self.sourceFile)
219         if not my_file.exists():
220             os.makedirs(my_file)
221         my_file = Path(self.saveFile)
222         if not my_file.exists():
223             os.makedirs(my_file)
224 
225         # 循环下载
226         for i in range(len(m3u8s)):
227             m3u8_url = m3u8s[i]
228             web_url = m3u8_url.partition(substr)[0];
229             file_name = re.sub('\s+', '', names[i]).strip()
230             if keys.__len__() is 0:
231                 key = ''
232             else:
233                 key = keys[i].encode('utf8')
234             merge_ts_path = f'{file_name}.mp4'
235             self.m3u8_url = m3u8_url
236             self.url = web_url
237             self.merge_ts_path = merge_ts_path
238             self.key = key
239             self.sum =0
240             # down = MY_GUI(web_url, m3u8_url, merge_ts_path, key)  # 构造方法
241             ts_list = self.get_available_IP()  # 第一步、获取真正的ts 列表
242             self.download_with_multi_process(ts_list)  # 开始多线程下载
243             self.decodeFile()
244 
245     # reset
246     def reset(self):
247         self.log_data_Text.delete(1.0,END)
248         self.request_m3u8_Text.delete(1.0,END)
249         self.request_separator_Text.delete(1.0,END)
250         self.request_fileName_Text.delete(1.0,END)
251         self.request_key_Text.delete(1.0,END)
252     #获取当前时间
253     def get_current_time(self):
254         current_time = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
255         return current_time
256 
257 
258     #日志动态打印
259     def write_log_to_Text(self,logmsg):
260         global LOG_LINE_NUM
261         current_time = self.get_current_time()
262         logmsg_in = str(current_time) +" " + str(logmsg) + "\n"      #换行
263         self.log_data_Text.insert(END, logmsg_in)
264 
265 
266 def gui_start():
267     init_window = Tk()              #实例化出一个父窗口
268     ZMJ_PORTAL = MY_GUI(init_window)
269     # 设置根窗口默认属性
270     ZMJ_PORTAL.set_init_window()
271 
272     init_window.mainloop()          #父窗口进入事件循环,可以理解为保持窗口运行,否则界面不展示
273 
274 
275 gui_start()
View Code

 2.python exe update

  1 from tkinter import *
  2 import time
  3 import urllib.request
  4 import http.cookiejar
  5 import urllib.error
  6 import urllib.parse
  7 import re
  8 import socket
  9 import os
 10 from pathlib import Path
 11 
 12 from Cryptodome.Cipher import AES
 13 from concurrent.futures import ThreadPoolExecutor
 14 LOG_LINE_NUM = 0
 15 
 16 class MY_GUI():
 17     # 初始化方法 构造方法
 18     def __init__(self, init_window_name):
 19         self.init_window_name=init_window_name
 20         self.playlist_url = None
 21         self.total=0
 22         self.max_num = 250
 23         self.header = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
 24                        "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
 25                        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0",
 26                        "Connection": "keep-alive"}
 27         self.cjar = http.cookiejar.CookieJar()
 28         self.cookie = urllib.request.HTTPCookieProcessor(self.cjar)
 29         self.opener = urllib.request.build_opener(self.cookie)
 30         urllib.request.install_opener(self.opener)
 31 
 32         self.pool = ThreadPoolExecutor(max_workers=10)
 33         self.sum = 0
 34         # 利用socket模块,使得每次重新下载的时间变短
 35         socket.setdefaulttimeout(20)
 36 
 37     def download_file(self, url, target):
 38         # 解决下载不完全问题且避免陷入死循环
 39         try:
 40             urllib.request.urlretrieve(url, target)
 41         except socket.timeout:
 42             count = 1
 43             while count <= 5:
 44                 try:
 45                     urllib.request.urlretrieve(url, target)
 46                     break
 47                 except socket.timeout:
 48                     err_info = url + ' Reloading for %d time' % count if count == 1 else 'Reloading for %d times' % count
 49                     print(END, str(err_info) + '\n')
 50                     count += 1
 51                 except:
 52                     # 解决远程主机关闭问题
 53                     self.download_file(url, target)
 54             if count > 5:
 55                 print(str('downloading fialed!'))
 56         except:
 57             # 解决远程主机关闭问题
 58             self.download_file(url, target)
 59 
 60     # 打开 m3u8
 61     def open_web(self, url):
 62         try:
 63             response = self.opener.open(url, timeout=3)
 64         except urllib.error.URLError as e:
 65             print(END, str('open ' + url + ' error') + '\n')
 66             if hasattr(e, 'code'):
 67                 print(END, str(e.code) + '\n')
 68             if hasattr(e, 'reason'):
 69                 print(END, str(e.reason) + '\n')
 70         else:
 71             return response.read()
 72 
 73     '''第一步、解析m3u8'''
 74     def get_available_IP(self):
 75         print(END, str('开始获取真实的url') + '\n')
 76         data = self.open_web(self.m3u8_url).decode('utf-8')
 77         tv_lists = re.findall(',\n(.*).ts\n', data)
 78         self.total = tv_lists.__len__()
 79         return tv_lists
 80 
 81     # 下载.ts
 82     def download_for_multi_process(self, ts):
 83         ts_url = ts + ".ts"
 84         str_style = "%05d" % self.sum
 85         path_str = str_style + '.ts'
 86         downUrl = self.url + ts_url
 87         downPath = self.sourceFile + path_str
 88         if os.path.isfile(downPath) and os.path.getsize(downPath) > 0:
 89             print(END, str("file already exist") + '\n')
 90         else:
 91             self.download_file(downUrl, downPath)
 92         self.sum = self.sum + 1
 93         jd = str(self.sum)+"/"+str(self.total)
 94         print(END, str("进度:" +jd) + '\n')
 95 
 96     # 开始线程
 97     def download_with_multi_process(self, ts_list):
 98         print(END, str('开始多线程下载') + '\n')
 99         task = self.pool.map(self.download_for_multi_process, ts_list)  # 此时非阻塞
100         for t in task:  # 此时会变成阻塞
101             pass
102 
103     '''第四步、合并ts文件'''
104     def merge_ts_file_with_os(self):
105         print(END, str('开始合并') + '\n')
106         # 合并ts文件
107         os.chdir(self.chdir)
108         shell_str = f'copy /b *.ts {self.merge_ts_path}'
109         os.system(shell_str)
110         os.system(f'del /Q *.ts')
111         os.chdir(self.sourceFile)
112         os.system(f'del /Q *.ts')
113         os.chdir(self.chdir)
114         print(END, str('合并完成') + '\n')
115 
116     # 解密
117     def decodeFile(self):
118         key = self.key
119         self.chdir = self.sourceFile
120         if len(key):
121             # key=bytes(key)
122             cryptor = AES.new(key, AES.MODE_CBC, key)
123             # 读取ts文件
124             sourceFile = self.sourceFile
125             savefile_path = self.saveFile
126             list_file = os.listdir(sourceFile)
127             for file in list_file:
128                 c_fule_name = file
129                 file_line = file
130                 if ".ts" in c_fule_name:
131                     fo = open(os.path.join(sourceFile, file_line), 'rb');
132                     if len(key):  # AES 解密,有key就是需要解密
133                         with open(os.path.join(savefile_path, c_fule_name), 'ab') as f:
134                             f.write(cryptor.decrypt(fo.read()))
135             print(END, str("解密完成") + '\n')
136             self.chdir = self.saveFile
137         self.merge_ts_file_with_os()  # 合并ts文件
138 
139     #设置窗口
140     def set_init_window(self):
141         self.init_window_name.title("ts文件下载工具_v2.0   by: 龙林基")           #窗口名
142         self.init_window_name.geometry('500x600+10+10')
143         #标签
144         self.init_data_label = Label(self.init_window_name, text="请求数据")
145         self.init_data_label.grid(row=0)
146 
147         self.request_m3u8_label= Label(self.init_window_name, text="m3u8_url:")
148         self.request_m3u8_label.grid(row=2)
149         self.request_m3u8_Text = Entry(self.init_window_name, width=55)
150         self.request_m3u8_Text.grid(row=2, column=1, pady=5)
151 
152         self.request_separator_label = Label(self.init_window_name, text="separator:")
153         self.request_separator_label.grid(row=3)
154         self.request_separator_Text = Entry(self.init_window_name, width=55)  # separator录入框
155         self.request_separator_Text.grid(row=3, column=1, pady=5)
156 
157         self.request_fileName_label = Label(self.init_window_name, text="file_name:")
158         self.request_fileName_label.grid(row=4)
159         self.request_fileName_Text = Entry(self.init_window_name, width=55)  # fileName录入框
160         self.request_fileName_Text.grid(row=4, column=1, pady=5)
161         self.request_fileName_Text.insert(0, "fileName")
162 
163         self.request_key_label = Label(self.init_window_name, text="key:")
164         self.request_key_label.grid(row=5)
165         self.request_key_Text = Entry(self.init_window_name, width=55)  # ket录入框
166         self.request_key_Text.grid(row=5, column=1, pady=5)
167 
168 
169         self.request_sourceFile_label = Label(self.init_window_name, text="sourceFile:")
170         self.request_sourceFile_label.grid(row=6)
171         self.request_sourceFile_Text = Entry(self.init_window_name, width=55)  # sourceFile录入框
172         self.request_sourceFile_Text.grid(row=6, column=1, pady=5)
173         self.request_sourceFile_Text.insert(0, "D:\\soft\\python\\project\\download\\dd\\")
174 
175         self.request_saveFile_label = Label(self.init_window_name, text="saveFile:")
176         self.request_saveFile_label.grid(row=8)
177         self.request_saveFile_Text = Entry(self.init_window_name, width=55)  # saveFile录入框
178         self.request_saveFile_Text.grid(row=8, column=1, pady=5)
179         self.request_saveFile_Text.insert(0, "D:\\soft\\python\\project\\download\\decode\\")
180 
181         # 按钮
182         self.submit_button = Button(self.init_window_name, text="submit", width=5,
183                                     command=self.runmain)  # 调用内部方法  加()为直接调用
184         self.submit_button.grid(row=12, column=0, sticky=W, pady=5)
185         self.reset_button = Button(self.init_window_name, text="reset", width=5,
186                                    command=self.reset)  # 调用内部方法  加()为直接调用
187         self.reset_button.grid(row=12, column=1, sticky=W, pady=5)
188 
189     # 主函数
190     def runmain(self):
191         m3u8s = []
192         names = []
193         keys = []
194         substr = str(self.request_separator_Text.get())
195         if len(str(self.request_m3u8_Text.get())) > 1:
196             m3u8s = str(self.request_m3u8_Text.get()).split(",")
197         if len(str(self.request_fileName_Text.get())) > 1:
198             names = str(self.request_fileName_Text.get()).split(",")
199         if len(str(self.request_key_Text.get())) > 1:
200             keys = str(self.request_key_Text.get()).split(",")
201         # 下载路径
202         self.sourceFile = str(self.request_sourceFile_Text.get()).split("\n")[0]
203         self.saveFile = str(self.request_saveFile_Text.get()).split("\n")[0]
204         # 判断路径是否存在
205         my_file = Path(self.sourceFile)
206         if not my_file.exists():
207             os.makedirs(my_file)
208         my_file = Path(self.saveFile)
209         if not my_file.exists():
210             os.makedirs(my_file)
211 
212         # 循环下载
213         for i in range(len(m3u8s)):
214             m3u8_url = m3u8s[i]
215             web_url = m3u8_url.partition(substr)[0];
216             file_name = re.sub('\s+', '', names[i]).strip()
217             if keys.__len__() is 0:
218                 key = ''
219             else:
220                 key = keys[i].encode('utf8')
221             merge_ts_path = f'{file_name}.mp4'
222             self.m3u8_url = m3u8_url
223             self.url = web_url
224             self.merge_ts_path = merge_ts_path
225             self.key = key
226             self.sum =0
227             # down = MY_GUI(web_url, m3u8_url, merge_ts_path, key)  # 构造方法
228             ts_list = self.get_available_IP()  # 第一步、获取真正的ts 列表
229             self.download_with_multi_process(ts_list)  # 开始多线程下载
230             self.decodeFile()
231 
232     # reset
233     def reset(self):
234         # self.log_data_Text.delete()
235         self.request_m3u8_Text.delete(0, END)
236         self.request_separator_Text.delete(0, END)
237         self.request_fileName_Text.delete(0, END)
238         self.request_key_Text.delete(0, END)
239     #获取当前时间
240     def get_current_time(self):
241         current_time = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
242         return current_time
243 
244 
245     #日志动态打印
246     def write_log_to_Text(self,logmsg):
247         global LOG_LINE_NUM
248         current_time = self.get_current_time()
249         logmsg_in = str(current_time) +" " + str(logmsg) + "\n"      #换行
250         self.log_data_Text.insert(END, logmsg_in)
251 
252 
253 def gui_start():
254     init_window = Tk()              #实例化出一个父窗口
255     ZMJ_PORTAL = MY_GUI(init_window)
256     # 设置根窗口默认属性
257     ZMJ_PORTAL.set_init_window()
258 
259     init_window.mainloop()          #父窗口进入事件循环,可以理解为保持窗口运行,否则界面不展示
260 
261 
262 gui_start()
View Code

 

 

 4.更换pip源为阿里云:

pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/

5.可以执行如下命令:pip install pycryptodomex ,即安装新版本的加密解密库

然后引入改成如下方式:


from Cryptodome.Hash import SHA256
from Cryptodome.Cipher import AES
from Cryptodome.Cipher import DES

posted on 2019-11-17 15:59  longlinji  阅读(822)  评论(0编辑  收藏  举报