1. 程式人生 > >Python3 根據m3u8下載視訊,批量下載ts檔案並且合併

Python3 根據m3u8下載視訊,批量下載ts檔案並且合併

Python3 根據m3u8下載視訊,批量下載ts檔案並且合併

m3u8是蘋果公司推出一種視訊播放標準,是一種檔案檢索格式,將視訊切割成一小段一小段的ts格式的視訊檔案,然後存在伺服器中(現在為了減少I/o訪問次數,一般存在伺服器的記憶體中),通過m3u8解析出來路徑,然後去請求,是現在比較流行的一種載入方式,諸如騰訊視訊之類大多都是切割成ts流進行載入。

示例程式碼:

import os, shutil
import urllib.request, urllib.error, requests

# 開啟並讀取網頁內容
def getUrlData(url):
    try:
        urlData 
= urllib.request.urlopen(url, timeout=20) # .read().decode('utf-8', 'ignore') return urlData except Exception as err: print(f'err getUrlData({url})\n', err) return -1 # 下載檔案-urllib.request def getDown_urllib(url, file_path): try: urllib.request.urlretrieve(url, filename
=file_path) return True except urllib.error.URLError as e: # hasttr(e, 'code'),判斷e 是否有.code屬性,因為不確定是不是HTTPError錯誤,URLError包含HTTPError,但是HTTPError以外的錯誤是不返回錯誤碼(狀態碼)的 if hasattr(e, 'code'): print(e.code) # 列印伺服器返回的錯誤碼(狀態碼),如403,404,501之類的 elif hasattr(e, 'reason
'): print(e.reason) # 列印錯誤原因 def getVideo_urllib(url_m3u8, path, videoName): print('begin run ~~\n') # urlData = getUrlData(url_m3u8).readlines() urlData = getUrlData(url_m3u8) num = 0 tempName_video = os.path.join(path, f'{videoName}.ts') # f'{}' 相當於'{}'.format() 或 '%s'%videoName # print(urlData) for line in urlData: # 解碼,由於是直接使用了所抓取的連結內容,所以需要按行解碼,如果提前解碼則不能使用直接進行for迴圈,會報錯 # 改用上面的readlines()或readline()也可以,但更繁瑣些,同樣需要按行解碼,效率更低 url_ts = line.decode('utf-8') tempName_ts = os.path.join(path, f'{num}.ts') # f'{}' 相當於'{}'.format() if not '.ts' in url_ts: continue else: if not url_ts.startswith('http'): # 判斷字串是否以'http'開頭,如果不是則說明url連結不完整,需要拼接 # 拼接ts流視訊的url url_ts = url_m3u8.replace(url_m3u8.split('/')[-1], url_ts) print(url_ts) getDown_urllib(url_ts, tempName_ts) # 下載視訊流 if num == 0: # 重新命名,已存在則自動覆蓋 shutil.move(tempName_ts, tempName_video) num += 1 continue cmd = f'copy /b {tempName_video}+{tempName_ts} {tempName_video}' res = os.system(cmd) if res == 0: os.system(f'del {tempName_ts}') if num == 20: # 限制下載的ts流個數,這個視訊挺長有四百多個.ts檔案,所以限制一下 break num += 1 continue print(f'Wrong, copy {num}.ts-->{videoName}.ts failure') return False os.system(f'del {path}/*.ts') # 呼叫windows命令列(即cmd)工具,執行命令 filename = os.path.join(path, f'{videoName}.mp4') shutil.move(tempName_video, filename) print(f'{videoName}.mp4 finish down!') if __name__ == '__main__': url_m3u8 = 'http://wscdn.alhls.xiaoka.tv/201886/2f5/75a/HoHdTc1LjUaBjZbJ/index.m3u8' path = r'E:\pydevworkspaces\project\product\epgw\videos' videoName = url_m3u8.split('/')[-2] getVideo_urllib(url_m3u8, path, videoName)

注:(1)僅限windows下使用,如果要在Linux上使用需要修改合併命令;

        (2)修改檔名時,特意選擇shutil模組(可以看作os的高階版)的move方法,雖然move主要是用來移動檔案的,重新命名算是附帶的,不過強制覆蓋的特點在這裡很有用,避免中斷後重新下載時重新命名產生異常。