视频网站上面都要钱,第三方网站普遍慢,而且都是m3u8技术搭建的网站,MP4被分成非常多的ts文件,下载后必须合并才能保存和观看。有个下载神器叫xdm,能自动识别m3u8网页中的m3u8下载合并成MP4,而且是多线程下载,速度非常好,这个工具是我最近才发现的,而下载m3u8的脚本是多年前用ruby编写的,最近开始用python,才进行了改写。
其中用到了ffmpeg工具,和wget命令行下载工具,为什么不要python的request呢,主要是还的编写断点续传,麻烦,另外一直使用linux惯了,wget用的多,就调用他了,同学们可自行下载windows版本,并加入PATH环境变量。
#!/usr/bin/python3
import sys
import re
import os
import threading
import time
import os.path
def download(url,ts):
global time_out
return(os.system("wget -U \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36\" -cq -t 1 -T " + str(time_out) + " " + url))
def t_down(url,ts,f_arr):
global down_i
down_i += 1
if download(url,ts)!=0:
f_arr.append([url,ts])
#print("redown "+url)
down_i -= 1
print("\n")
print("usage: m3u8 url mp4_filename thread_num time_out\n")
print("\n")
if len(sys.argv) < 3:
sys.exit()
url=sys.argv[1]
#f_arr为ts文件列表
f_arr=[[]]
#判断是否为续传
if os.path.isfile("f_arr.txt"):
with open("f_arr.txt", "r") as f1:
for line in f1.readlines():
arr = line.split(" ")
f_arr[0].append(arr)
else:
#下载m3u8文件
f_m3u8 = re.search("\/([^\/]*\.m3u8)",url).group(1)
pre_url = re.sub("\/([^\/]*\.m3u8)","",url)+"/"
short_url=re.search("(^https:\/\/[^\/]*)\/",url).group(1)
user_agent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
os.system("wget -U \"" + user_agent + "\" -O " + f_m3u8 + " " + url)
#逐层解析,循环下载,得到最终的m3u8文件
find_m3u8 = True
while find_m3u8:
find_m3u8 = False
with open(f_m3u8, "r") as f1:
lines = f1.readlines()
if len(lines)<10:
for line in lines:
if ".m3u8" in line:
url= pre_url + line
f_m3u8 = re.search("\/([^\/]*\.m3u8)",url).group(1)
pre_url = re.sub("\/([^\/]*\.m3u8)","",url)+"/"
short_url=re.search("(^https:\/\/[^\/]*)\/",url).group(1)
os.system("wget -U \"" + user_agent + "\" -O " + f_m3u8 + " " + url)
find_m3u8 = True
break
#生成本地m3u8文件
with open("filelist.m3u8", 'w') as f:
with open(f_m3u8, "r") as f1:
for line in f1.readlines():
if ".ts" in line:
s1=re.search("([^\/]*\.ts)",line).group(1)
f.write(s1+"\n")
f_arr[0].append([pre_url +s1,s1])
elif ".key" in line:
s1=re.search("[\/|\"]([^\/]*\.key)",line).group(1)
f.write('#EXT-X-KEY:METHOD=AES-128,URI="' + s1 +'"\n')
f_arr[0].append([pre_url +s1,s1])
else:
f.write(line)
#wget计数,全局变量
down_i = 0
#下载线程数
if len(sys.argv) > 3:
down_num = int(sys.argv[3])
else:
down_num = 20
#全局变量 超时时间,每次循环加一
if len(sys.argv) > 4:
time_out= int(sys.argv[4])
else:
time_out = 20
#下载ts文件
i = 0
while len(f_arr[i])>0:
time_out += 1
k = 0
while down_i > 0:
k += 1
if k <= time_out * down_i:
time.sleep(1)
else:
os.system("taskkill /F /im wget.exe")
#记录进度
with open("f_arr.txt", 'w') as f:
for pl in f_arr[i]:
f.write(pl[0]+" "+pl[1]+"\n")
j=0
f_arr.append([])
for pl in f_arr[i]:
j += 1
while True:
if down_i < down_num:
if j <= down_num:
time.sleep(1)
print(str(i+1)+" down " + str(j) + "/" + str(len(f_arr[i])) +" "+ pl[0])
t = threading.Thread(target=t_down,args=(pl[0],pl[1],f_arr[i+1]))
t.start()
break
else:
time.sleep(1)
i += 1
#转码
mp4 = sys.argv[2] + ".mp4"
while down_i > 0:
time.sleep(1)
os.system("ffmpeg -loglevel quiet -allowed_extensions ALL -i filelist.m3u8 -c copy " + mp4)
把要下载的多个m3u8文件连接存入一个txt文件,并调用它,另外也可以打开自动关机,省点电。
后两个参数分别是 线程数,默认20,单个ts文件超时时间,默认20秒,部分网站不允许太多下载线程,可适当减少。
@echo off
setlocal enabledelayedexpansion
echo,
echo usage: m3u8all m3u8_list_file thread_num time_out
echo,
set file=%1
set i=0
for /f "delims=" %%f in (%file%) do (
set /a i=i+1
echo !i!
echo %%f
mkdir !i!
cd !i!
python d:\src\python\m3u8\m3u8_wget.py %%f !i! %2 %3
cd ..
)
rem shutdown /p
目前,网上有不少m3u8资源站,连续剧都整理好列表了,只许复制到一个txt文件中,就可以用上面脚本一键下载,并关机。非常方便,如果是单个文件xdm也是个不错的选择,不过xmd的合并成功率不高,我的合并方法是将下载的m3u8列表文件生成一个本地版本,再用ffmpeg内置命令合并的。本来ffmpeg就有下载和合并的功能,但是单线程操作,速度慢,文件合并不全。