Python通過m3u8文件下載合並ts視頻的操作
前段時間,接到一個需求,要求下載某一個網站的視頻,然後自己從網上查閱瞭相關的資料,在這裡做一個總結。
1. m3u8文件
m3u8是蘋果公司推出一種視頻播放標準,是一種文件檢索格式,將視頻切割成一小段一小段的ts格式的視頻文件,然後存在服務器中(現在為瞭減少I/o訪問次數,一般存在服務器的內存中),通過m3u8解析出來路徑,然後去請求,是現在比較流行的一種加載方式。目前,很多新聞視頻網站都是采用這種模式去加載視頻。
M3U8文件是指UTF-8編碼格式的M3U文件。M3U文件是記錄瞭一個索引純文本文件,打開它時播放軟件並不是播放它,而是根據它的索引找到對應的音視頻文件的網絡地址進行在線播放。原視頻數據分割為很多個TS流,每個TS流的地址記錄在m3u8文件列表中。
下面就是m3u8文件的格式。
#EXTM3U #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-ALLOW-CACHE:YES #EXT-X-TARGETDURATION:15 #EXTINF:6.916667, out000.ts #EXTINF:10.416667, out001.ts #EXTINF:10.416667, out002.ts #EXTINF:1.375000, out003.ts #EXTINF:1.541667, out004.ts #EXTINF:7.666667, out005.ts #EXTINF:10.416667,
2. ts文件處理
隻有m3u8文件,需要下載ts文件
ts文件能正常播放,但太多而小,需要合並 有ts文件
但因為被加密無法播放,需要解碼
在這裡我隻記錄下前兩個步驟,因為,我目前研究的比較少,還沒有遇到ts被加密的情況。
3. 分析舉例
那麼下面,我就正式舉一個網站,第一財經網(直接點擊)跟大傢正式的講解下。
這是該網站的視頻。如下圖:
點擊第一個視頻,這就是我們這次要爬取的視頻。
然後鼠標右鍵點擊,選擇”檢查” 或者按F12鍵,進入開發者模式,查看網頁代碼。
然後,點擊Network ,再點擊other,尋找請求地址中帶有m3u8和ts標記的請求地址。
不懂,請看下圖。有一點,很重要。網站通過切割後ts加載視頻,並不是沒有規律的,而是通過m3u8文件附帶的。也就說,網站一定是先加載m3u8文件,然後根據m3u8文件,去請求ts文件。所以,如果你找不到m3u8文件的話,你可以先找第一個ts文件,然後往上面翻,一定能找到m3u8文件。
再點擊這個m3u8文件,右側對應的就是它的請求地址。
請求地址如下:
https://ycalvod.yicai.com/record/live/cbn/ca233887-1443-4bdf-b762-3b4b3a217085_LD.m3u8?auth_key=1575703722-0-0-6f09e9a156491f027a035e31c238c48c&ycfrom=yicaiwww
你可以把上面那個地址,輸入瀏覽器地址框內,下載下來。也可以通過查看源碼,找到該功能的對應的html代碼。
這是下載下來的m3u8文件。
從圖片可以看出來,每一個ts文件都是相對的地址,所以下面我們就需要找到絕對地址。
ts文件地址如下:
https://ycalvod.yicai.com/record/live/cbn_yld/1575111614_3446078.ts
上面,我們已經把這個網站的視頻加載模式分析的很透徹,下面就開始擼代碼瞭。
4. 獲取ts文件
def getTsUrl(): ts_url_list = [] baseUrl = "https://ycalvod.yicai.com/record/live" with open("ca233887-1443-4bdf-b762-3b4b3a217085_LD.m3u8", "r", encoding="utf-8") as f: m3u8Contents = f.readlines() for content in m3u8Contents: if content.endswith("ts\n"): ts_Url = baseUrl + content.replace("\n", "").replace("..", "") ts_url_list.append(ts_Url) print(ts_Url) return ts_url_list
5. 下載ts文件
def download_ts_video(download_path, ts_url_list): download_path = r"C:\Users\Administrator\Desktop\AiShu\下載視頻\TS視頻" for i in range(len(ts_url_list)): ts_url = ts_url_list[i] try: response = requests.get(ts_url, stream=True, verify=False) except Exception as e: print("異常請求:%s" % e.args) return ts_path = download_path + "\{}.ts".format(i) with open(ts_path, "wb+") as file: for chunk in response.iter_content(chunk_size=1024): if chunk: file.write(chunk) print("TS文件下載完畢!!")
這就是我本地下載好的ts切割視頻
6. 合並TS視頻
def heBingTsVideo(download_path,hebing_path): all_ts = os.listdir(download_path) with open(hebing_path, 'wb+') as f: for i in range(len(all_ts)): ts_video_path = os.path.join(download_path, all_ts[i]) f.write(open(ts_video_path, 'rb').read()) print("合並完成!!")
最後的結果如下:
7. 完整的代碼
有興趣的小夥伴,可以研究下。
import requests,os def getTsUrl(): ts_url_list = [] baseUrl = "https://ycalvod.yicai.com/record/live" with open("ca233887-1443-4bdf-b762-3b4b3a217085_LD.m3u8", "r", encoding="utf-8") as f: m3u8Contents = f.readlines() for content in m3u8Contents: if content.endswith("ts\n"): ts_Url = baseUrl + content.replace("\n", "").replace("..", "") ts_url_list.append(ts_Url) print(ts_Url) return ts_url_list def download_ts_video(download_path, ts_url_list): download_path = r"C:\Users\Administrator\Desktop\AiShu\下載視頻\TS視頻" for i in range(len(ts_url_list)): ts_url = ts_url_list[i] try: response = requests.get(ts_url, stream=True, verify=False) except Exception as e: print("異常請求:%s" % e.args) return ts_path = download_path + "\{}.ts".format(i) with open(ts_path, "wb+") as file: for chunk in response.iter_content(chunk_size=1024): if chunk: file.write(chunk) print("TS文件下載完畢!!") def heBingTsVideo(download_path,hebing_path): all_ts = os.listdir(download_path) with open(hebing_path, 'wb+') as f: for i in range(len(all_ts)): ts_video_path = os.path.join(download_path, all_ts[i]) f.write(open(ts_video_path, 'rb').read()) print("合並完成!!") if __name__ == '__main__': download_path = r"C:\Users\Administrator\Desktop\AiShu\下載視頻\TS視頻" hebing_path = r"C:\Users\Administrator\Desktop\AiShu\下載視頻\合並TS視頻\第一財經.mp4" ts_url_list = getTsUrl() download_ts_video(download_path, ts_url_list) heBingTsVideo(download_path,hebing_path)
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。如有錯誤或未考慮完全的地方,望不吝賜教。
推薦閱讀:
- None Found