M3U8流视频数据爬虫详解三:M3U8视频网络数据爬虫实现

您所在的位置:网站首页 如何爬取网站文件 M3U8流视频数据爬虫详解三:M3U8视频网络数据爬虫实现

M3U8流视频数据爬虫详解三:M3U8视频网络数据爬虫实现

2024-06-03 19:47| 来源: 网络整理| 查看: 265

M3U8流视频数据爬虫详解三:M3U8视频网络数据爬虫实现 下载一级M3U8文件使用Chrome开发者工具从页面中获取URL数据Python下载代码实现更简单的方法 下载二级M3U8文件下载并保存密钥文件和IV数据阿里大学TS视频的密钥文件分析解密TS文件阿里大学TS视频的密钥解密算法使用AES-128解密TS文件 小结

本文是《M3U8流视频数据爬虫详解》系列教程中的第三篇。前两篇M3U8流视频数据爬虫详解一:M3U8视频文件详解和M3U8流视频数据爬虫详解二:M3U8视频网络数据分析与爬虫设计分别介绍了M3U8文件的基础知识。并且通过详细案例,介绍和讲解了使用Chrome开发者工具分析页面数据,并从数据记录中找到了最关键的数据文件和访问方法。最后,根据页面分析结果,我们给出了一套具体的M3U8视频爬虫设计思路。在本文中,我们将在上一篇的基础上,以实际案例,根据爬虫设计思路,实现一套具体的M3U8视频爬虫程序。特别感谢老船长老师在爬虫实现中给予的指导,本文引用老船长老师的文章并根据作者自己的实现进行了改动。 免责申明:本文是以教育为目的的教学讲解,不涉及和教唆任何非法获取数据,非法使用数据,和非法占有数据的行为。对于没有经过授权的数据爬取行为都是违规的,违法的。对于任何个人,团体或者机构,运用该技术从事任何违法违规行为的,自担风险。

下载一级M3U8文件

本文使用的具体案例是阿里大学的教学视频网站,视频样例为:

https://edu.aliyun.com/lesson_137_1545#_1545

按照M3U8流视频数据爬虫详解二:M3U8视频网络数据分析与爬虫设计文中的设计思路,首先我们要登陆该网页才能获取一级M3U8文件的下载地址。但是由于网站本身对于M3U8文件做了保护,页面中的M3U8文件URL只能访问一次。也就是说,如果浏览器访问了该页面,我们的爬虫程序就无法再次访问了。因此,我们需要在浏览器访问一级M3U8文件之前,获取该文件的URL地址,并阻止浏览器下载访问。这时我们又需要使用功能强大的Chrome开发者工具。

使用Chrome开发者工具从页面中获取URL数据

首先在Chrome浏览器中打开对应的网址(登陆以后的具体视频页面)。点击F12打开Chrome开发者工具。在“Sources”选项卡(顶端)中,点击“XHR/fetch Breakpoints”的加号,在编辑框中输入“m3u8”(本操作的意思是:当网页中有任何URL中包含m3u8字段的网络访问就暂停执行)。如图所示: 在这里插入图片描述 完成以上操作后重新刷新页面。此时Chrome开发者工具就会暂停在访问M3U8的代码位置。暂停后,我们可以点击左下方的{}图标提高暂停部分代码的可读性。如图所示: 在这里插入图片描述 随后Chrome开发者工具会显示一个相对容易阅读的源代码(Javascript源代码)。简单的分析以下JS代码,可以发现M3U8文件的URL藏在e.url变量中。我们可以在下方的“Console”窗口中输入e.url并回车,就能显示出来具体的URL地址。如图所示: 在这里插入图片描述 注意,由于阿里大学的视频URL每次访问都会发生变化,因此在实际操作中,具体的URL可能和本文中的不一样。

Python下载代码实现

获取到具体的URL以后,我们就可以开始编写爬虫下载程序了。本文将不讲解基础Python编程,对于没有任何Python编程背景的读者,建议自学以下Python基础编程,Python的Requests类等。以下是一段非常简单的HTTP下载代码,用来下载给定的URL(本文为M3U8文件和后面的TS文件,Key文件)。

# -*- coding: utf-8 -*- import requests url = "https://edu.aliyun.com/hls/2452/playlist/QhGsP7IelnAKHq4KPMPXxZWINSvyMYSD.m3u8?courseId=137" try: req = requests.get(url) req.raise_for_status() req.encoding = req.apparent_encoding print(req.text) except: traceback.print_exc()

运行以上代码后,终端会显示以下内容(也就是M3U8的文件内容):

#EXTM3U #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=704,NAME=标清 https://edu.aliyun.com/hls/2452/stream/sd/CyxsgtS0Rkr2uTZ2cv6dQCNbd4RVLj4E.m3u8?courseId=137 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1096,NAME=高清 https://edu.aliyun.com/hls/2452/stream/hd/0FYIJA5K9E9Bq8ocFW3MJ3WSunGLBtul.m3u8?courseId=137

如果大家在运行代码过程中,代码返回404结果。大概率是因为该M3U8下载地址URL已经过期,需要重复以上步骤重新获取新的URL地址。至此,我们已经成功的下载了一级M3U8文件,并获得了两个不同网络环境下的二级M3U8文件URL。

更简单的方法

作者在此处提供一个更简便的方法,同样是上面设置断点的方法。我们在第一次暂停之后,不做任何操作,单击resume运行到下一断点,如下图: 在这里插入图片描述 等到第二次暂停时意味着第二次遇到了m3u8文件,即二级m3u8文件。那么此时的一级m3u8文件就是可以获取的了,我们双击它下载到本地: 在这里插入图片描述 用编辑器打开此文件就可以看到一级m3u8文件中的内容,也就是二级m3u8文件的url了: 在这里插入图片描述 注:在github的代码中,我们采取了此方法获得二级m3u8文件的url。

下载二级M3U8文件

根据以上得出的结果,我们使用以下代码可以下载二级M3U8文件。

# -*- coding: utf-8 -*- import requests url = "https://edu.aliyun.com/hls/2452/stream/hd/0FYIJA5K9E9Bq8ocFW3MJ3WSunGLBtul.m3u8?courseId=137" try: req = requests.get(url) req.raise_for_status() req.encoding = req.apparent_encoding print(req.text) except Exception as e: print(e)

运行代码以后,终端显示以下内容:

404 Client Error: Not Found for url: https://edu.aliyun.com/hls/2452/stream/hd/0FYIJA5K9E9Bq8ocFW3MJ3WSunGLBtul.m3u8?courseId=137

前文说过,阿里大学的视频URL只能访问一次,第二次访问就会出现404的错误。然后以上URL并没有被访问过。所以我们排除由于第二次访问而出现404的问题。因此推测很可能是需要验证登陆信息。所以,我们又要回到Chrome开发者工具中的网络窗口,点击一个网络数据记录并拷贝对应的Cookie,User-Agent和Referer等信息。如图所示: 在这里插入图片描述 随后将网络数据记录中的Cookie,User-Agent和Referer等信息拷贝到代码中(以上图片中的Cookie内容中有账号信息,因此进行了脱敏处理)。再重复以上步骤重新获取新的URL并运行代码。

# -*- coding: utf-8 -*- import requests url = "https://edu.aliyun.com/hls/2452/stream/sd/EyX0ufPyrPZecw5oyB8aQ5c4bDiQNVp6.m3u8?courseId=137" try: headers = { "Cookie":"replace data with your own cookie from chrome developer tools", "Referer":"https://edu.aliyun.com/bundles/customweb/lib/cloud-player/1.1.37.3/player.html", "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" } req = requests.get(url, headers=headers) req.raise_for_status() req.encoding = req.apparent_encoding print(req.text) except Exception as e: print(e)

经过以上操作以后,终端会显示出完整的M3U8的文件内容,如图所示: 在这里插入图片描述

下载并保存密钥文件和IV数据

M3U8中的加密选项是可选的。因此不同的视频资源,有的会对TS文件加密并提供密钥(Key)文件URL地址和IV数据;有的则不会做任何处理;有些视频服务甚至对密钥(Key)文件进行了二次加密,类似于先要把密钥文件解密获取到密钥(Key)的元数据以后,再使用密钥(Key)的元数据对TS文件解密。比较值得庆幸的是,我们选择的样例视频,只使用原始的密钥和IV加密向量对TS文件进行加密。

阿里大学TS视频的密钥文件分析

在本例中,TS视频的加密方式也比较特殊。首先在M3U8文件中,每一个TS文件之前都有一个Key文件的URL和一个不一样的IV加密向量。但是在Chrome开发者工具中我们可以发现(如下图),其实页面上只加载了两个Key文件(第一个和第二个)。因此,我们可以推断第一个TS文件使用的是第一个key密钥进行解密的;第二个和以后的TS文件都是使用第二个Key密钥进行解密的。 在这里插入图片描述 另外,由于IV加密向量都是不一样的,那么从第二个和以后的TS文件用的是同一个IV加密向量么?这个问题需要验证。因为Key密钥文件和IV加密向量配对才能解密TS文件。我们使用Chrome开发者工具分析得出,在每一个TS文件被下载以后,都会调用一个onKeyLoading的方法。在该方法中,我们发现每一次TS文件对应得IV数据都是不一样的。例如下图中的IV数据,对应与M3U8中的第五条IV数据(42对应的16进制数为0x2a,174对应的16进制数为0xae)。 在这里插入图片描述 在这里插入图片描述 因此,我们只需要将key和IV数据保存下来。以下是在面向对象的编程中的解析二级m3u8文件中ts文件的url,key的url和iv的示例代码,解析出来的内容被分别放在self.ts_url_list,self.key_url_dealed和self.iv_dealed中。

def parse_m3u8(self, m3u8): self.m3u8 = m3u8 self.ts_url_list = re.findall(r'http.*\.ts', self.m3u8) key_url_list = re.findall(r'EXT-X-KEY:METHOD=AES-128,URI="http.*"', self.m3u8) iv_list = re.findall(r'IV=0x.{32}', self.m3u8) self.key_url_dealed = [] for key in key_url_list: key = key[30:-1] self.key_url_dealed.append(key) self.iv_dealed = [] for iv in iv_list: iv = iv[5:] self.iv_dealed.append(iv)

在后面解密过程中我们会对key再进行处理,并将ts文件,key和iv存储到文件中,此处先给出解密部分的示例代码:

def decoding(self): key = "" for i in range(0,len(self.ts_url_list)): ts_url = self.ts_url_list[i] print("No", i, "file\t",ts_url) ts = self.save_ts_url(ts_url) key_name = ts_url.split("/")[-1].split(".ts")[0] + ".key" iv_name = ts_url.split("/")[-1].split(".ts")[0] + ".iv" ts_name = ts_url.split("/")[-1].split(".ts")[0] + "_convert.ts" if i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3