python脚本——m3u8视频流下载

测试环境:python 3.7

部分m3u8文件样本:

#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:60
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-START-TIME:1080
#EXT-X-PROGRAM-DATE-TIME:2021-04-27T14:01:15+08:00
#EXTINF:1,
612048020_1773822331_1.ts?start=0&end=185555&type=mpegts&resolution=1280x720&sign=c5bf5843178951ada765c8e5d62865e2&t=6089b22d&us=12975f1b-50fc-4a55-b825-f4a429987355
#EXT-X-PROGRAM-DATE-TIME:2021-04-27T14:01:16+08:00
#EXTINF:1,
612048020_1773822331_1.ts?start=185556&end=372051&type=mpegts&resolution=1280x720&sign=c5bf5843178951ada765c8e5d62865e2&t=6089b22d&us=12975f1b-50fc-4a55-b825-f4a429987355
#EXT-X-PROGRAM-DATE-TIME:2021-04-27T14:01:17+08:00
#EXTINF:1,
612048020_1773822331_1.ts?start=372052&end=557795&type=mpegts&resolution=1280x720&sign=c5bf5843178951ada765c8e5d62865e2&t=6089b22d&us=12975f1b-50fc-4a55-b825-f4a429987355
#EXT-X-PROGRAM-DATE-TIME:2021-04-27T14:01:18+08:00
#EXTINF:1,
612048020_1773822331_1.ts?start=557796&end=747299&type=mpegts&resolution=1280x720&sign=c5bf5843178951ada765c8e5d62865e2&t=6089b22d&us=12975f1b-50fc-4a55-b825-f4a429987355
#EXT-X-PROGRAM-DATE-TIME:2021-04-27T14:01:19+08:00
#EXTINF:1,
612048020_1773822331_1.ts?start=747300&end=937743&type=mpegts&resolution=1280x720&sign=c5bf5843178951ada765c8e5d62865e2&t=6089b22d&us=12975f1b-50fc-4a55-b825-f4a429987355
#EXT-X-PROGRAM-DATE-TIME:2021-04-27T14:01:20+08:00
#EXTINF:1,
612048020_1773822331_1.ts?start=937744&end=1124803&type=mpegts&resolution=1280x720&sign=c5bf5843178951ada765c8e5d62865e2&t=6089b22d&us=12975f1b-50fc-4a55-b825-f4a429987355
#EXT-X-PROGRAM-DATE-TIME:2021-04-27T14:01:21+08:00
#EXTINF:1,
612048020_1773822331_1.ts?start=1124804&end=1308667&type=mpegts&resolution=1280x720&sign=c5bf5843178951ada765c8e5d62865e2&t=6089b22d&us=12975f1b-50fc-4a55-b825-f4a429987355
#EXT-X-PROGRAM-DATE-TIME:2021-04-27T14:01:22+08:00
#EXTINF:1,

想要下载m3u8视频,第一件事就是找到m3u8的文件地址。可以浏览器F12抓包找,然后下载到本地,用下面的脚本来解析m3u8下载分流。

以下脚本包含有:m3u8分流下载、ts视频合并。

# _*_encoding:UTF-8_*_
import urllib.request
import urllib.parse
import re
import time
import sys
import os

#根据m3u8文件下载ts子文件
#strM3U8:		m3u8文件,该文件中存放了分流信息。
#urlHead: 		因为分流信息是没有前面的地址的,所以需要提供url的前半部分。可以通过浏览器F12抓包找到。
#				浏览器在播放时会下载分流,可以抓到很多的包,把链接复制下来对比一下提取前半部分。
#strSaveDir:	下载保存的目录,会自动创建。
def downloadM3U8(strM3U8, urlHead, strSaveDir):
    print("开始下载:" + strM3U8)

    if not os.path.exists(strSaveDir):
        os.mkdir(strSaveDir);

    f = open(strM3U8, 'r', encoding='utf-8')
    if f==None:
        print('open failed:'+strM3U8)
        return 
    
    strContext = f.read()

    nIndex = 0

    listFile = re.findall(r'.*start=.*', strContext)
    for file in listFile:
        #if(nIndex > 154):
        #    break

        print("[%08d] %s" % (nIndex, file))
        strUrl = urlHead + file

        strPath = "%s\\%08d.ts" % (strSaveDir, nIndex)

        try:
        	#这里在下载时可能会出现超时问题,所以加入异常重试机制,这也是一些下载器没有的功能
        	#下载器通常会傻傻的等到死。这也是这个脚本诞生的原因[狗头]。
            urllib.request.urlretrieve(strUrl, strPath)
        except BaseException:
            print("文件下载失败,10秒后重试:" + strPath)
            time.sleep(10)
            continue
        
        nIndex += 1

    f.close()

    print("下载完毕")

#合并ts类型文件
#strTsDir:		下载好的ts分流目录
#nRecursion: 	递归计数,用来命名合并文件的,默认0.
#bDelSrc:		合并完了要不要删除源文件。建议调用时不删,防止合并出错。合并没问题了手动删。
#				这个参数主要是用来删除递归临时文件的。
def MergeTsFile(strTsDir, nRecursion, bDelSrc):
    nMergeNum = 0       #合并次数
    strTotalPath = ""

    print("合并ts文件,递归次数:%d" % (nRecursion))

    for nIndex in range(99999):

        if nRecursion == 0:
            strTsPath = "%s\\%08d.ts" % (strTsDir, nIndex)
        else:
            strTsPath = "%s\\%08d_%08d.ts" % (strTsDir, nRecursion-1, nIndex)
        if not os.path.exists(strTsPath):
            break

        if nIndex % 10 == 0:
            strTotalPath = "%s\\%08d_%08d.ts" % (strTsDir, nRecursion, nMergeNum) 

            if os.path.exists(strTotalPath):
                os.remove(strTotalPath)
            fTmp = open(strTotalPath, "w")
            fTmp.close()

            nMergeNum += 1

        sysCmd = 'copy /b "%s"+"%s" "%s">>log.txt' % (strTotalPath, strTsPath, strTotalPath)
        print(sysCmd)
        os.system(sysCmd)

        if bDelSrc:
            os.remove(strTsPath)

    if nMergeNum <= 1:
        return

    nRecursion += 1
    MergeTsFile(strTsDir, nRecursion, True)

def main():
    print("开始:")

    strSaveDir = "X:\\Desktop\\tempVideo"
    strUrl = "https://www.xxxxxx.com/d7beb5c4vodcq13013243"

    strSaveDir = "X:\\Desktop\\tempVideo\\"
    downloadM3U8("X:\\Desktop\\playlist_eof.m3u8", strUrl, strSaveDir)

    #合并ts视频流
    nRecursion = 0      #递归次数,如果存在上万的分流,是分批次每10个1组进行递归合并的。
    MergeTsFile("X:\\Desktop\\tempVideo", nRecursion, False)

    print('退出')

    #下载完成后关机,如果视频太大可以设置自动关机
    #os.system("shutdown -s -t 60")

if __name__ == "__main__":
    main()

最终合并完的格式是ts格式的,也可以播放,如果要转mp4可以下载格式工厂。这个工具挺好用的。

上面的脚本仅供测试使用,如果实际使用,需要根据自己的需求进行手动修改。上面的脚本不支持m3u8加密流的下载。如果遇到加密,需要使用AES对其进行解密。并在m3u8文件中下载对应的加密key文件。

你可能感兴趣的:(Python开发,python)