一、背景
在爬虫方面包括图片,文字,视频,音频等的获取。受到速度的限制,视频的爬取较为麻烦,因为视频是进行切片处理的采取的方式是hls,这是苹果公司制定的一个方案。它会把内容切片,用.m3u8进行组织,在m3u8里面记录了断点的位置,将所有的片段下载下来在拼接就可以连接成整个视频。目前较大的视频都是采取这样的方式。同时m3u8的格式也可以被h5直接读取,这样从理论上和实际过程中解决了视频的传输问题。模型图如下。
二、文件信息
2.1 .m3u8的头文件格式
用检索我们可以在source/media中看到一个.m3u8的文件,通过对这个文件进行访问,可以看到下面的结果。
这一部分包括了文件格式的定义,以及加密方式,和解密的密钥。
# EXTM3U:.m3u8文件的格式定义 # EXT-X-KEY: 密钥的信息 # METHOD: 加密的方法,这里采用的是AES-128的加密方式 # URI: 密钥的地址,需要获取访问得到密钥的信息 # IV: 偏移量,AES加密的方法,通过这个密钥就可以解密,获取正确的视频信息
结果:
2.2 每个.ts的文件片段
每一个.m3u8的片段都包含了这个片段的密钥,加密方法,用于解析视频内容。
# EXINF:片段切割的大小,大概是10s左右 # v.f...:下载的地址,每一个.ts片段都保留一个地址,可能相同可能不同 # EXT-X-KEY:加密的方式和密钥,每一个视频都有一个密钥,可能相同,可能不同 # METHOD:加密方式,AES-128的加密方式
结果
三、解密
3.1 PyCryptodome安装
在有密钥的情况下我们需要进行解密,不然下载的文件就是无法播放的。解密的方法参考加密的手法。这里的密钥是AES,因此使用AES的解密方法去解密。
使用以下的指令安装
# PyCryptodome的安装,由于版本的问题,在使用AES模块的时候,安装PyCryptodome pip install PyCryptodome
结果
3.2 构建解码器与解码
首先获取到VI,然后获取到key,构建一个解码器
from Crypto.Cipher import AES url_key = "key.key" # 省略写法 content_key = requests.get(url_key).content # 获取key值 vi = "0x00000000000000000000000000000000" # vi值一样 vt = vi.replace("0x", "")[:16].encode() # 偏移码 ci = AES.new(content_key, AES.MODE_CBC, vt) # 构建解码器 content = requests.get(url_content_ts).content # 获取加密视频内容 content_ts = ci.decrypt(content) # 解码ts中的二进制格式
3.3 对获取的content解密
完整的代码
import requests import os import re from Crypto.Cipher import AES url = "https://1252524126.vod2.myqcloud.com/9764a7a5vodtransgzp1252524126/0176cbbd5285890799673243539/drm/v.f230.m3u8?" data = { "time": "" } download_url = "https://1252524126.vod2.myqcloud.com/9764a7a5vodtransgzp1252524126/0176cbbd5285890799673243539/drm/" """ 列举一个单位格大小: #EXTINF:2.000000, v.f230.ts?start=0&end=158495&type=mpegts #EXT-X-KEY:METHOD=AES-128,URI="https://app.xiaoe-tech.com/get_video_key.php?edk=CiCTzP%2B6jBR9H5awSTdnrwcCQzZlldD%2BTYaAr%2FlaHOwsPBCO08TAChiaoOvUBCokYjRhNjFiNTgtMmVhNy00OWYxLTgwZGMtZTE0NTIyODc5YWIy&fileId=5285890799673243539&keySource=VodBuildInKMS",IV=0x00000000000000000000000000000000 """ def download(): url_key = "https://app.xiaoe-tech.com/get_video_key.php?edk=CiCTzP%2B6jBR9H5awSTdnrwcCQzZlldD%2BTYaAr%2FlaHOwsPBCO08TAChiaoOvUBCokYjRhNjFiNTgtMmVhNy00OWYxLTgwZGMtZTE0NTIyODc5YWIy&fileId=5285890799673243539&keySource=VodBuildInKMS" content_key = requests.get(url_key).content # 获取key值 download_path = os.getcwd() + r"\download" if not os.path.exists(download_path): os.mkdir(download_path) m3u8_content = requests.get(url, params=data).text print(m3u8_content) exit() result = re.compile(r"v\.f230\.ts\?start=[0-9]+&end=[0-9]+&type=mpegts", re.S).findall(m3u8_content) # 匹配.ts的文件地址 vi = "0x00000000000000000000000000000000" vt = vi.replace("0x", "")[:16].encode() # 偏移码 ci = AES.new(content_key, AES.MODE_CBC, vt) # 构建解码器 for i in enumerate(result): print(f"正在下载:{i[0]}") content_ts = requests.get(download_url + str(i[1])).content with open(download_path + "\\" + str(i[0] + 1) + ".mp4", ‘ab‘) as f: f.write(ci.decrypt(content_ts)) # 将内容解码 f.flush() if __name__ == ‘__main__‘: download()
四、总结
上述讲述了.m3u8文件的爬取和解析方法,例如直播的爬取,或者是是视频的爬取都涉及到上述的内容。此方法需要自己分析一下内容,没有写成接口的形式,同时这个解码是AES-128的方式,在遇到其他加密方法自行查阅相关解码方式。
五、参考:
下面的blog是一下参考
https://blog.csdn.net/weixin_40346015/article/details/102595690
https://www.jianshu.com/p/98756e274fa0
https://www.52pojie.cn/thread-971265-1-1.html
详细的介绍:https://pakchoi.me/2016/06/21/hls-fe/
包安装问题:https://www.cnblogs.com/new-june/p/9401002.html
原文地址:https://www.cnblogs.com/future-dream/p/12582918.html