2021.6.18补充:未失效,但需要一些特殊的方法绕过cdn的限制
本脚本已于2020/12/16失效,大概讲讲相应的思路吧。
1.腾讯视频存在部分付费资源,例如《云首发相声大会》等,需要付费才能完整观看。
我们简单看一下这种付费的m3u8链接和普通的m3u8文件有何不同吧。
https://*.v.smtcdns.com/vipts.tc.qq.com/.../055_z00341icz95.321004.ts.m3u8?ver=4 #EXTM3U #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-TARGETDURATION:15 #EXT-X-PLAYLIST-TYPE:VOD #EXTINF:12.000, 00_z00341icz95.321004.1.ts?index=0&start=0&end=12000&brs=0&bre=2900275&ver=4 #EXTINF:12.280, 01_z00341icz95.321004.1.ts?index=1&start=12000&end=24280&brs=2900276&bre=6104547&ver=4 #EXTINF:11.560, 02_z00341icz95.321004.1.ts?index=2&start=24280&end=35840&brs=6104548&bre=9642143&ver=4 #EXTINF:12.360, 03_z00341icz95.321004.1.ts?index=3&start=35840&end=48200&brs=9642144&bre=16151831&ver=4 #EXTINF:9.520, 04_z00341icz95.321004.1.ts?index=4&start=48200&end=57720&brs=16151832&bre=19113019&ver=4 #EXT-X-ENDLIST
可以看到里面只有四个分片。
https://*.v.smtcdns.com/vipts.tc.qq.com/.../o0035306o0e.321004.ts.m3u8?ver=4 #EXTM3U #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-TARGETDURATION:14 #EXT-X-PLAYLIST-TYPE:VOD #EXTINF:6.875, 00_o0035306o0e.321004.1.ts?index=0&start=0&end=6875&brs=0&bre=1163343&ver=4 #EXTINF:12.500, 01_o0035306o0e.321004.1.ts?index=1&start=6875&end=19375&brs=1163344&bre=3374787&ver=4 #EXTINF:12.500, 02_o0035306o0e.321004.1.ts?index=2&start=19375&end=31875&brs=3374788&bre=5565739&ver=4 #EXTINF:12.500, 03_o0035306o0e.321004.1.ts?index=3&start=31875&end=44375&brs=5565740&bre=11094067&ver=4 #EXTINF:12.500, 04_o0035306o0e.321004.1.ts?index=4&start=44375&end=56875&brs=11094068&bre=13035731&ver=4 #EXTINF:12.500, 05_o0035306o0e.321004.1.ts?index=5&start=56875&end=69375&brs=13035732&bre=16923007&ver=4 ... #EXTINF:5.548, 0537_o0035306o0e.321004.17.ts?index=537&start=5649833&end=5655381&brs=131368008&bre=131484003&ver=4 #EXT-X-ENDLIST
2.大概几年前的时候,腾讯视频在网页端提供的还是5-6分钟一段的MP4片段,后来虽然开始做分片,但完整片段的url依然是可以使用的,简单来说就可以把m3u8文件简化为形如https://*.v.smtcdns.com/vipts.tc.qq.com/…/vid.321004.*.ts?ver=4的片段。
对于付费资源来说,我们可能只能获取到第一个分片的地址,如https://*.v.smtcdns.com/vipts.tc.qq.com/…/vid.321004.1.ts?ver=4,但把分片的index手动替换后会发现,后续的分片也是可以下载的,例如https://*.v.smtcdns.com/vipts.tc.qq.com/…/vid.321004.4.ts?ver=4
3.想法大概是,腾讯(以前)没有做url是普通链接还是预览链接的鉴定,所以只需要拼出分片就可以下载。所以写了如下的脚本来将预览链接变为可下载的链接。
4.但是2020/12/16发现,腾讯做了相关的鉴权,前几个分片可以自由下载,但之后的分片被限速了,根本不可能完整下载完整个视频。
5.因为本脚本已经失效,所以将相关的思路整理到这里,感兴趣的也可以试试看有没有办法解除速度限制。over:)
import requests
import os
from urllib.parse import urljoin
cfg ={
"corePath": r"D:\Tool\N_m3u8DL-CLI\N_m3u8DL-CLI_v2.5.7.exe",
"workDir": r"D:\Tool\N_m3u8DL-CLI"
}
def download(name):
print("Ready to download...")
os.system(cfg["corePath"]+" \"" + name + ".m3u8\" --workDir \"" + cfg["workDir"] + "\" --saveName \"" + name + "\" --minThreads \"30\" --enableDelAfterDone")
print("Download Complete!")
def createdata(url):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36",
"Cookie": "",
"Range": "bytes=0-10"
}
data = "#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-TARGETDURATION:360\n"
index = 1
while True:
clipurl = url.replace("*", str(index))
print("Trying to get clip %d..." % index, end="")
i = 1
while i <= 3:
try:
r = requests.get(clipurl, headers=headers, timeout=2)
if r.status_code == 206:
print("OK")
data += "#EXTINF:300\n%s\n" % clipurl
i = 4
elif r.status_code == 404:
print("Not Exist...Leaving...")
i = 4
else:
print("Unexpected Error...Leaving...")
i = 4
except requests.exceptions.RequestException:
i += 1
if r.status_code != 206:
break
index += 1
data += "#EXT-X-ENDLIST"
return data
def createfile(data, name):
print("Starting writing m3u8 file...")
with open(name + ".m3u8", "w+", encoding="utf8") as file:
file.write(data)
print("Writing to m3u8 file...Finished")
def standardclip(url):
relapath = url.split("/")[-1].split("_")[-1].replace(".m3u8", "")
index = max(relapath.find("321004"), relapath.find("320181"), relapath.find("326002"), relapath.find("322016"), relapath.find("322014"))
relapath = relapath[:index+6] + ".*" + relapath[index+6:]
return urljoin(url, relapath)
def main():
print("This tool is using to download video from TencentVideo for free...")
m3url = input("Please input the m3u8 url:")
taskname = input("Please input the task name:")
clipurl = standardclip(m3url)
data = createdata(clipurl)
createfile(data, taskname)
download(taskname)
if __name__ == '__main__':
main()