import requests
import os, time
from concurrent.futures import ThreadPoolExecutor, wait
import sys
# from Crypto.Cipher import AES
finishedNum = 0
allNum = 0
fileList = []
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0'}
class m3u8_downloader():
def download(self,downloadLink, name):
global finishedNum
global allNum
for _ in range(10):
try:
req = requests.get(downloadLink, headers=headers, timeout=15)
with open(f"{name}", "wb") as f:
f.write(req.content)
f.flush()
finishedNum += 1
print(f"{name}下载成功, 总进度{round(finishedNum / allNum * 100, 2)}% ({finishedNum}/{allNum})")
break
except:
if _ == 9:
print(f"{name}下载失败")
else:
print(f"{name}正在进行第{_}次重试")
def merge_file(self,path, name):
global fileList
cmd = "copy /b "
for i in fileList:
if i != fileList[-1]:
cmd += f"{i} + "
else:
cmd += f"{i} {name}"
os.chdir(path)
with open('combine.cmd', 'w') as f:
f.write(cmd)
os.system("combine.cmd")
if ".ts" in fileList[0]:
os.system('del /Q *.ts')
# elif ".mp4" in fileList[0]:
# os.system('del /Q *.mp4')
os.system('del /Q *.cmd')
def downloader(self,url, downloadPath, name, threadNum):
global allNum
global fileList
print("读取文件信息中...")
if not os.path.exists(downloadPath):
os.mkdir(downloadPath)
# 查看是否存在
if os.path.exists(f"{downloadPath}/{name}"):
print(f"视频文件已经存在,如需重新下载请先删除之前的视频文件")
return
content = requests.get(url, headers=headers).text.split('\n')
if "#EXTM3U" not in content[0]:
raise BaseException(f"非M3U8链接")
# .m3u8 跳转
for video in content:
if ".m3u8" in video:
if video[0] == '/':
url = url.split('//')[0] + "//" + url.split('//')[1].split('/')[0] + video
elif video[:4] == 'http':
url = video
else:
url = url.replace(url.split('/')[-1], video)
print(url)
content = requests.get(url, headers=headers).text.split('\n')
urls = []
for index, video in enumerate(content):
if '#EXTINF' in video:
if content[index + 1][0] == '/':
downloadLink = url.split('//')[0] + "//" + url.split('//')[1].split('/')[0] + content[index + 1]
elif content[index + 1][:4] == 'http':
downloadLink = content[index + 1]
elif content[index + 1][:5] == 'https':
downloadLink = url.replace(url.split('/')[-1], content[index + 1])
else:
if content[index + 2][0] == '/':
downloadLink = url.split('//')[0] + "//" + url.split('//')[1].split('/')[0] + content[index + 2]
elif content[index + 2][:4] == 'http':
downloadLink = content[index + 2]
elif content[index + 2][:5] == 'https':
downloadLink = content[index + 2]
else:
downloadLink = url.replace(url.split('/')[-1], content[index + 1])
urls.append(downloadLink)
allNum = len(urls)
pool = ThreadPoolExecutor(max_workers=threadNum)
futures = []
start = time.time()
for i, downloadLink in enumerate(urls):
print(downloadLink)
if ".mp4" in downloadLink:
tsname = str(i) + '.mp4'
elif ".ts" in downloadLink:
tsname = str(i) + '.ts'
fileList.append(tsname)
futures.append(pool.submit(self.download, downloadLink, f"{downloadPath}/{tsname}"))
wait(futures)
end = time.time()
print(f"运行完成,共用时", end - start)
self.merge_file(downloadPath, name + '.mp4')
print(f"合并完成")
print(f"文件下载成功,尽情享用吧")
if __name__ == '__main__':
videoUrl = input("请输入m3u8地址:")
name = input('请输入视频名称:')
dpath = "G:/films/" + name
# threadNum = int(sys.argv[3])
d=m3u8_downloader()
d.downloader(videoUrl, dpath, name, 64)