python 爬虫 m3u8视频 AES加/解密 问题讨论

python 爬虫 m3u8视频 AES加/解密 相关问题

最近在了解爬虫 记录一下近期的情况

公司在研究机器学习和深度学习于是就有了这篇文章,本文说的是爬取百度的视频思路,目前为止爬虫还未结束但并没有成功,遇到一些问题进行不下去了,这些问题将在本文展开讨论和分享。本文涉及到百度大脑视频其中爬取的视频并未用于商业以及其他非法用途,仅仅是为了个人方便学习和技术锻炼,如有侵权联系删除。

  1. 首先我们进入官网登录之后页面是这个样子的 点击进入百度大脑
    在这里插入图片描述
    然后随意选择一篇自己喜欢的课程,加入课程,进入课程学习
    在这里插入图片描述

2.接下来点击开始学习
在这里插入图片描述
3. 先看一下网络,这里进到页面之后打控制台重新刷新一下,在点击播放的时候又会出现一部分的网络请求
在这里插入图片描述
红框内点击播放是加载的接口需要注意
在这里插入图片描述

这里分析此网站采用的是流式媒体 m3u8视频的格式 不懂的同学自行谷歌
此时我们点开这个文件来查看一下文件内容如下在这里插入图片描述
这里贴出来一部分
看不懂m3u8文件的同学点击这里有详细介绍 m3u8 文件格式详解

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:13
#EXT-X-KEY:METHOD=AES-128,URI="https://drm.media.baidubce.com/v1/tokenVideoKey?videoKeyId=mda-kiqkczejn4b8fnqs",IV=0xe3508bcf5e9bf17c6e0fcb55ed8a5157,KEYFORMAT=media-drm-token
#EXTINF:12.500000,
mda-kiqkczejn4b8fnqs.m3u8.0.ts
#EXT-X-KEY:METHOD=AES-128,URI="https://drm.media.baidubce.com/v1/tokenVideoKey?videoKeyId=mda-kiqkczejn4b8fnqs",IV=0xe3508bcf5e9bf17c6e0fcb55ed8a5157,KEYFORMAT=media-drm-token
#EXTINF:8.333333,
mda-kiqkczejn4b8fnqs.m3u8.1.ts
#EXT-X-KEY:METHOD=AES-128,URI="https://drm.media.baidubce.com/v1/tokenVideoKey?videoKeyId=mda-kiqkczejn4b8fnqs",IV=0xe3508bcf5e9bf17c6e0fcb55ed8a5157,KEYFORMAT=media-drm-token
#EXTINF:12.500000,
mda-kiqkczejn4b8fnqs.m3u8.2.ts
#EXT-X-KEY:METHOD=AES-128,URI="https://drm.media.baidubce.com/v1/tokenVideoKey?videoKeyId=mda-kiqkczejn4b8fnqs",IV=0xe3508bcf5e9bf17c6e0fcb55ed8a5157,KEYFORMAT=media-drm-token
#EXTINF:8.333333,
mda-kiqkczejn4b8fnqs.m3u8.3.ts
#EXT-X-KEY:METHOD=AES-128,URI="https://drm.media.baidubce.com/v1/tokenVideoKey?videoKeyId=mda-kiqkczejn4b8fnqs",IV=0xe3508bcf5e9bf17c6e0fcb55ed8a5157,KEYFORMAT=media-drm-token
#EXTINF:8.333333,
mda-kiqkczejn4b8fnqs.m3u8.4.ts
#EXT-X-KEY:METHOD=AES-128,URI="https://drm.media.baidubce.com/v1/tokenVideoKey?videoKeyId=mda-kiqkczejn4b8fnqs",IV=0xe3508bcf5e9bf17c6e0fcb55ed8a5157,KEYFORMAT=media-drm-token
#EXTINF:12.500000,
mda-kiqkczejn4b8fnqs.m3u8.5.ts

4.由此推断出此视频肯定是加密的,所以我们要对视频解码才能在本地播放。
5.接下来直接上代码吧,让代码来帮我讲

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# @author souldou-1257096360@qq.com
# @date 2021/4/1
# @file 视频检测index.py

# 用到的依赖,这里重点说一下 Crypto 的依赖 肯定会遇到问题,直接谷歌一下就能解决
import os
import requests
import json
import datetime
from Crypto.Cipher import AES



class Reptile(object):
    def __init__(self, params: object):
        self.url, self.token, self.data = params['url'], params['token'], params['data']
        print('Reptile!!!,\nurl:{},\ndata:{}\n'.format(self.url, self.data))
        self.header = {} #自己的请求头信息 自己模拟
        # 创建问价夹
        download_path = os.getcwd() + "\download"
        if not os.path.exists(download_path):
            os.mkdir(download_path)
        # 新建日期文件夹
        download_path = os.path.join(download_path, '视频' + datetime.datetime.now().strftime('%Y%m%d_%H%M%S'))
        os.mkdir(download_path)
        all_content = requests.get(url = self.url, headers = self.header).text  # 获取M3U8的文件内容
        # 保存m3u8文件为文本
        with open(download_path + "\m3u8.txt", 'w+') as f:
            f.write(all_content)
            f.close()
        file_line = all_content.split("\n")  # 读取文件里的每一行
        # 通过判断文件头来确定是否是M3U8文件
        if file_line[0] != "#EXTM3U":
            raise BaseException(u"非M3U8的链接")
        else:
            unknow = True  # 用来判断是否找到了下载的地址
            for index, line in enumerate(file_line):
                unknow = False
                if "#EXT-X-KEY" in line:
                    # 找m3u8文件中的参数和解密的key,请求连接
                    URI_http = line[line.find("URI"):line.rfind('"')].split('"')[1]
                    # 找m3u8文件中的参数和解密的IV
                    IV = line[line.find("IV"):].split(',')[0].split('=')[1]
                    # 拿到请求返回的真实key
                    tokenVideoKey = requests.get(
                        url = URI_http + '&playerId=' + '&playerId=pid-1-5-1&token=' + self.token)
                    data = json.loads(tokenVideoKey.content)
                    # encryptedVideoKey 就是借口返回的key
                    encryptedVideoKey, videoKeyId = data['encryptedVideoKey'], data[
                        'videoKeyId']
                    # 开始解密文件和保存
                    # 拼出ts片段的URL,拼接处ts文件的请求地址:https://jh0p4t0rh9rs9610ryc.exp.bcevod.com/mda-kimg4q6rjx1351mk/mda-kimg4q6rjx1351mk.m3u8.15.ts 这样的格式(此链接无效)
                    pd_url = self.url.rsplit("/", 1)[0] + "/" + file_line[index + 2]
                    # 获取ts视频文件
                    res = requests.get(pd_url)
                    print('res:', res)
                    c_fule_name = str(file_line[index + 2])
                    print(c_fule_name + ".mp4")
                    if encryptedVideoKey and len(encryptedVideoKey):
                        # AES 解密
                        KEY = bytes(encryptedVideoKey, encoding = 'utf-8')
                        IV = bytes(IV, encoding = 'utf-8')
                        
                        cont = res.content
                        
                        print('key:{}\nIV:{}\n'.format(KEY, IV))
                        
                        crypto = AES.new(KEY, AES.MODE_CBC, IV)
                        c_fule_name + ".mp4"
                        with open(os.path.join(download_path, c_fule_name), 'ab') as f:
                            f.write(crypto.decrypt(cont))
                            pass
                        pass
                    else:
                        print('AES 解密跳过')
                        with open(os.path.join(download_path, c_fule_name), 'ab') as f:
                            f.write(res.content)
                            f.flush()
                            pass
                        pass
                    pass
                pass
            if unknow:
                raise BaseException("未找到对应的下载链接")
            else:
                print("下载完成")
            pass
        pass


if __name__ == '__main__':
	# 这里的url 自己在浏览器控制台复制 .m3u8 的请求地址,token获取 下边看截图,会在/v1/tokenVideoKey?的这个接口中获取
    params = {
        "data" : { },
        "url"  : 'https://jh0p4t0rh9rs9610ryc.exp.bcevod.com/mda-kjjf4mvng54wteir/mda-kjjf4mvng54wteir.m3u8',
        "token": '89b5222c412618429cc7c71245825a50c94a73bbeb13f29f56d95c625bae50fb_ae4b649c2a1c435d905425892dab42b1_1617769864',
    }
    reptile = Reptile(params)

在这里插入图片描述

最后重点说一下遇到的问题:以上是关键的代码并非全部,其中会报 IV 字节的错误,暂未解决此问题,后续更新
在这里插入图片描述
这里的KEY 和 IV值应该还需要作进一步的处理,目前问题就出在这里,发此篇文章的目的主要就是想大家一起讨论。

这里联系方式,有兴趣的同学滴滴我哈
125709636@qq.com

本文暂且说到这里,后续继续跟进。

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值