聲明:本文只作學習研究,禁止用于非法用途,否則后果自負,如有侵權,請告知刪除,謝謝!
背景
在某一天,群友分享了一些小視頻,手機端可以正常觀看,但是到了電腦上,輸入網址之后會下載下來一個m3u8格式的文件,這就讓我犯了難。所以我就研究了一下,并使用Python來將該文件爬取了下來。
參考文章如下:
西北亂跑娃 — python m3u8庫
Python 手把手實現M3U8視頻抓取
python實戰(zhàn)案例:解析m3u8視頻文件
python爬取m3u8視頻教程
1.文件信息
鏈接圖如下
下載下來呢,也是m3u8文件,一種非常特殊的文件。我們點擊查看,就可以查看到
3u8的一些信息
我在這里屏蔽了網址
,免得暴露我在下載什么hhhhh
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-KEY:METHOD=AES-128,URI="https://h09.t*********wc.com/20220703/9K***sCCV/30**0kb/hls/key.key"
#EXTINF:1.16,
https://h09.*********.com/20220703/9K***V/300**b/hls/Foszl**SV.ts
#EXTINF:1.2,
https://h09.**********.com/20220703/9KR**CV/30**kb/hls/b7tCBoOu.ts
經過查閱資料,該文件的我信息大致如下
# EXTM3U:.m3u8文件的格式定義
# EXT-X-KEY: 密鑰的信息
# METHOD: 加密的方法,這里采用的是AES-128的加密方式
# URI: 密鑰的地址,需要獲取訪問得到密鑰的信息
# IV: 偏移量,AES加密的方法,通過這個密鑰就可以解密,獲取正確的視頻信息
那什么是m3u8呢?
M3U8 是 Unicode 版本的 M3U,用 UTF-8 編碼?!癕3U” 和 “M3U8” 文件都是蘋果公司使用的 HTTP Live
Streaming(HLS) 協議格式的基礎,這種協議格式可以在 iPhone 和 Macbook 等設備播放。
通俗點可以理解為,一個視頻文件拆分為多個.ts片段的視頻文件,然后將所有的ts合成MP4文件就可以播放了。但是為什么有些在線或者m3u8的播放器會用不了呢?由于大部門的m3u8生成的結果不太一致,與該播放器的解密格式不一樣,所以導致打開。
一般來說,在m3u8文件中都會有key以及AES的偏移量IV,我們根據其中的URL來獲取他們,之后我們根據m3u8文件中的.ts
的文件URL來下載視頻片段,解密之后拼接成mp4
的文件就行了。
2.構造請求獲得m3u8文件
我們已經有了m3u8文件的URL,因此免去了抓包這一項工作。我們直接構造response即可
def get_file(url,count):
resp=requests.request('GET',url)
# print(resp.content)
with open('./m3u8_link/'+str(count)+'.m3u8','wb') as f:
f.write(resp.content)
3.獲得m3u8文件中的key以及偏移量IV
根據我們上一步獲得的文件內容,這里我選擇使用正則來匹配出來key以及IV對應的URL,之后在構造resp即可獲得其內容。
這里要說明一下,我們的m3u8文件中AES加密的時候是沒有使用IV的,所以使用時實際上令IV=Key
.*?
,經典的正則在爬蟲中的使用了。
def get_key(path):
with open(path, 'rb') as f:
file_content=str(f.read())
print(file_content)
key_link = re.search('URI=\"(.*?)\"', file_content).group(1)
key=requests.request('GET',key_link).content
return key
4.獲取.ts文件鏈接
其實這一步也可以使用正則來繼續(xù)匹配,但是我偷了一點小懶,使用了m3u8庫來進行匹配。
import m3u8
def get_ts_list(path):
m3u8_obj = m3u8.load(path)
ts_urls = []
for i, seg in enumerate(m3u8_obj.segments):
# if i<=100:
ts_urls.append(seg.uri)
# print(ts_urls)
return ts_urls
經過這一步之后,我們就獲得了m3u8文件中整個.ts
文件對應的URL,接下來只要根據.ts
文件對應的URL來獲取視頻片段,解密之后拼接就可以了。
5.進行解密
解密的庫 pip install pycryptodome
就是一些常規(guī)的AES解密操作了,我們獲得的m3u8文件中沒有IV偏移量,這里用使iv=key
即可。注意,AES要補0的,補字節(jié)0到16的倍數。
from Crypto.Cipher import AES
sprytor = AES.new(key, AES.MODE_CBC,iv)
# 獲取ts文件二進制數據
ts = requests.get(ts_url).content
# 密文長度不為16的倍數,則添加b"0"直到長度為16的倍數
# decrypt方法的參數需要為16的倍數,如果不是,需要在后面補二進制"0"
while len(ts) % 16 != 0:
ts += b"0"
with open(name, "ab") as file:
file.write(sprytor.decrypt(ts))
6.下載拼接
之后下載以字節(jié)流的形式進行拼接就可以了。文章來源:http://www.zghlxwxcb.cn/news/detail-412529.html
def download(ts_urls,key,iv,count,path):
name=path
print("視頻",count,"需要下載的文件長度為", len(ts_urls))
for i in range(len(ts_urls)):
ts_url=ts_urls[i]
if i%10==0:
print("視頻",count,"當前下載進度:",str(i/len(ts_urls)*100)[:4],'%')
# 如果連接末尾沒有.ts手動加上
ts_name = ts_url.split("/")[-1] + '.ts' # ts文件名
# 解密,new有三個參數,
# 第一個是秘鑰(key)的二進制數據,
# 第二個使用下面這個就好
# 第三個IV在m3u8文件里URI后面會給出,如果沒有,可以嘗試把秘鑰(key)賦值給IV
sprytor = AES.new(key, AES.MODE_CBC,iv)
# 獲取ts文件二進制數據
ts = requests.get(ts_url).content
# 密文長度不為16的倍數,則添加b"0"直到長度為16的倍數
while len(ts) % 16 != 0:
ts += b"0"
# 寫入mp4文件
with open(name, "ab") as file:
# # decrypt方法的參數需要為16的倍數,如果不是,需要在后面補二進制"0"
file.write(sprytor.decrypt(ts))
print(name, "下載完成")
其實還可以使用多線程優(yōu)化,完整項目請見本人的github。文章來源地址http://www.zghlxwxcb.cn/news/detail-412529.html
到了這里,關于Python爬取m3u8格式的視頻的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!