python 下载拉钩教育AES加密视频
说在前面:
下面我们要爬取的是拉钩教育课程上面的视频,课程已经购买过了。但是由于没有提供缓冲和下载视频的功能,所以就打算把视频通过python给下载下来,以下的文章都是参考博友的,自己总结下并学习学习。
正式爬取:
1.拉钩教育的网址:https://kaiwu.lagou.com/,输入自己的账号和密码 ,然后登陆进去,找到自己已经购买的课程(这里我就举这个例子)。
2.通过F12 抓包的方式,进入到控制台的network,最后找到的这个视频的请求地址,同时也找到视频的名字和地址(注意:cookies 和referer 字段 请求的时候一定要带上,因为电脑的原因截图没有显示出来)。
下面是请求头的代码,注意一定要带上cookie 和referer 字段,代码里面的cookie要修改成自己的,要不然会报错。
def __init__(self):self.url = 'https://gate.lagou.com/v1/neirong/kaiwu/getCourseLessons?courseId=131'self.headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36','Cookie': 'LG_LO7D','Referer': 'https://kaiwu.lagou.com/course/courseInfo.htm?courseId=131','Origin': 'https://kaiwu.lagou.com','Sec-fetch-dest': 'empty','Sec-fetch-mode': 'cors','Sec-fetch-site': 'same-site','x-l-req-header': '{deviceType:1}'}self.queue = Queue() # 初始化一个队列self.error_queue = Queue()self.save_folder = r"/Users/拉钩视频下载/"
3.分析请求地址和请求后的响应内容,不难发现 返回的数据是json格式,所以只需要使用json()模块解析数据就可以了。
4.现在已经知道请求的地址,然后我们就可以发送请求,再解析数据了。现在有许多的视频网站,都是通过m3u8的方式把视频分割成ts视频流的方式,所以本次我们要得到的就是m3u8文件地址,再通过m3u8文件找到每一个单独的ts视频的地址以及AES128加密的key以及iv偏移量。
具体代码如下:
通过parse_one方法得到了所有课程的m3u8以及课程名,通过字典的形式进行存储,然后把得到的字典传递给下一个方法。
def parse_one(self):""":return:获得所有的课程url和课程名 返回一个队列(请求一次)"""html = requests.get(url=self.url, headers=self.headers).textdit_message = json.loads(html)courseSectionList = dit_message['content']['courseSectionList']for course in courseSectionList:for i in course['courseLessons']:if i['videoMediaDTO'] == None:passelse:fileUrl = i['videoMediaDTO']['fileUrl']theme = i['theme']m3u8_dict = {fileUrl: theme} # fileUrl就是m3u8视频的url,theme为视频的名字if os.path.exists(os.path.join(self.save_folder, "{}.mp4".format(theme))):print("{}已经存在".format(theme))passelse:self.queue.put(m3u8_dict) # 将每个本地不存在的视频url(m3u8)和name加入到队列中return self.queue
5.同样的道理,我们还需要向m3u8文件地址发送请求,可以从此请求中获取ts 以及key相关的信息。
然后,从下面这些信息中拿到key(key的url已经找到了,通过requests发送请求即可得到真正的二进制的key )以及所有ts的url(这里ts的url只给出了部分需要自己拼接,用发送请求的url进行拼接)。
这是m3u8文件的内容:
下面是每一节课程下面视频的m3u8地址 和ts地址,可以找一下规律,然后自己拼接下地址:
m3u8地址:
https://1252043158.vod2.myqcloud.com/1d93b969vodtranscq1252043158/097fcc715285890799975988367/drm/v.f240.m3u8
ts地址:
https://1252043158.vod2.myqcloud.com/1d93b969vodtranscq1252043158/097fcc715285890799975988367/drm/v.f240.ts?start=0&end=124655&type=mpegts
https://1252043158.vod2.myqcloud.com/1d93b969vodtranscq1252043158/097fcc715285890799975988367/drm/v.f240.ts?start=124656&end=230319&type=mpegts
这部分代码如下:
def get_key(self, **kwargs):m3u8_dict = kwargsfor m3u8_url in m3u8_dict: # 获取某个视频的urlurl_split = m3u8_url.split('.')[0:-2]str_url = '.'.join(url_split)true_url = str_url.split('/')[0:-1]t_url = '/'.join(true_url) # 拼接ts的url前面部分html = requests.get(url=m3u8_url, headers=self.headers).text # 请求返回包含ts以及key数据message = html.split('\n') # 获取key以及ts的url# 通过正则表达式获取key的列表以及ts的列表key_parse = re.compile('URI="(.*?)"')key_list = key_parse.findall(html)key = requests.get(url=key_list[0], headers=self.headers).content # 一个m3u8文件中的所有ts对应的key是同一个 发一次请求获得m3u8文件的keyvideo_name = m3u8_dict[m3u8_url] # 视频的名字for i in message:if 'v.f240.ts?' in i:ts_url = t_url + '/' + i # ts_url 就是拼接后每一个ts 视频流地址self.write(key, ts_url, video_name, m3u8_dict)
代码解读:(对响应回来的数据进行各种切割拼接的操作以得到真正有用的内容)
- 1.遍历上一个请求穿过来的字典,通过这个m3u8_url可以拼接出ts真正的url
- 2.获取加密的秘钥key
- 3.将key,ts的url以及课程的名字传递给下一个方法
- 4.发送请求写入数据
6.破解AES128加密后视频,然后保存到本地,这部分代码如下:
def write(self, key, ts_url, name, m3u8_dict):save_wav = os.path.join(self.save_folder, '{}.mp4'.format(name))cryptor = AES.new(key, AES.MODE_CBC, iv=key)with open(save_wav, 'ab')as f:try:html = requests.get(url=ts_url, headers=self.headers).contentf.write(cryptor.decrypt(html))print('{},{}写入成功'.format(ts_url, name))except Exception as e:print('{}爬取出错'.format(name))while True:if f.close(): # 检查这个出问题的文件是否关闭 闭关则删除然后重新爬取,没关闭则等待10s,直到该文件被删除并重新爬取为止os.remove('{}.mp4'.format(name))print('{}删除成功'.format(name))thread = self.thread_method(self.get_key, m3u8_dict)print("开启线程{},{}重新爬取".format(thread.getName(), name))thread.start()thread.join()breakelse:time.sleep(10)
完整代码如下:
使用多线程threading 和 Queue来爬取,速度提升很多。
import threading
from queue import Queue
import re
import requests
import json
from Crypto.Cipher import AES
import time
import osclass LaGou_spider():def __init__(self):self.url = 'https://gate.lagou.com/v1/neirong/kaiwu/getCourseLessons?courseId=131'self.headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36','Cookie': 'LG_LOGI-9841821f-45eb-4135-9698-8d6b8280d898; LGUID=20200704113210-6a6a8c61','Referer': 'https://kaiwu.lagou.com/course/courseInfo.htm?courseId=131','Origin': 'https://kaiwu.lagou.com','Sec-fetch-dest': 'empty','Sec-fetch-mode': 'cors','Sec-fetch-site': 'same-site','x-l-req-header': '{deviceType:1}'}self.queue = Queue() # 初始化一个队列self.error_queue = Queue()self.save_folder = r"/Users/拉钩视频下载"def parse_one(self):""":return:获得所有的课程url和课程名 返回一个队列(请求一次)"""html = requests.get(url=self.url, headers=self.headers).textdit_message = json.loads(html)courseSectionList = dit_message['content']['courseSectionList']for course in courseSectionList:for i in course['courseLessons']:if i['videoMediaDTO'] == None:passelse:fileUrl = i['videoMediaDTO']['fileUrl']theme = i['theme']m3u8_dict = {fileUrl: theme} # fileUrl就是m3u8视频的url,theme为视频的名字if os.path.exists(os.path.join(self.save_folder, "{}.mp4".format(theme))):print("{}已经存在".format(theme))passelse:self.queue.put(m3u8_dict) # 将每个本地不存在的视频url(m3u8)和name加入到队列中return self.queuedef get_key(self, **kwargs):m3u8_dict = kwargsfor m3u8_url in m3u8_dict: # 获取某个视频的urlurl_split = m3u8_url.split('.')[0:-2]str_url = '.'.join(url_split)true_url = str_url.split('/')[0:-1]t_url = '/'.join(true_url) # 拼接ts的url前面部分html = requests.get(url=m3u8_url, headers=self.headers).text # 请求返回包含ts以及key数据message = html.split('\n') # 获取key以及ts的url# 通过正则表达式获取key的列表以及ts的列表key_parse = re.compile('URI="(.*?)"')key_list = key_parse.findall(html)key = requests.get(url=key_list[0], headers=self.headers).content # 一个m3u8文件中的所有ts对应的key是同一个 发一次请求获得m3u8文件的keyvideo_name = m3u8_dict[m3u8_url] # 视频的名字for i in message:if 'v.f240.ts?' in i:ts_url = t_url + '/' + i # ts_url 就是拼接后每一个ts 视频流地址self.write(key, ts_url, video_name, m3u8_dict)def write(self, key, ts_url, name, m3u8_dict):save_wav = os.path.join(self.save_folder, '{}.mp4'.format(name))cryptor = AES.new(key, AES.MODE_CBC, iv=key)with open(save_wav, 'ab')as f:try:html = requests.get(url=ts_url, headers=self.headers).contentf.write(cryptor.decrypt(html))print('{},{}写入成功'.format(ts_url, name))except Exception as e:print('{}爬取出错'.format(name))while True:if f.close(): # 检查这个出问题的文件是否关闭 闭关则删除然后重新爬取,没关闭则等待10s,直到该文件被删除并重新爬取为止os.remove('{}.mp4'.format(name))print('{}删除成功'.format(name))thread = self.thread_method(self.get_key, m3u8_dict)print("开启线程{},{}重新爬取".format(thread.getName(), name))thread.start()thread.join()breakelse:time.sleep(10)# 创建多线程方法def thread_method(self, method, value):thread = threading.Thread(target=method, kwargs=value)return threaddef main(self):global m3u8thread_list = []m3u8_dict = self.parse_one()while not m3u8_dict.empty():for i in range(10): # 创建10个线程并启动m3u8 = m3u8_dict.get() # 每次从队列取出一个对象 ,启动一个线程实例化对象,然后再放到线程列表中thread = self.thread_method(self.get_key, m3u8)thread.start()print(thread.getName() + '启动成功,{}'.format(m3u8))time.sleep(1)thread_list.append(thread)for k in thread_list:k.join() # 回收线程if __name__ == '__main__':run = LaGou_spider()run.main()
其实,我在这里有一个疑问 ,就是那个破解AES加密的时候,为什么iv也是key?
不应该是m3u8文件里面的那个iv偏移量吗?
cryptor = AES.new(key, AES.MODE_CBC, iv=key)
参考博客:Python爬虫实现全自动爬取拉钩教育视频
python 下载拉钩教育AES加密视频相关推荐
- Python爬虫实现全自动爬取拉钩教育视频
ps:改良之后的多线程版本在最后 背景 大饼加了不少技术交流群,之前在群里看到拉钩教育平台在做活动,花了1块钱买了套课程.比较尴尬的是大饼一般都会在上下班的路中学习下(路上时间比较久)而这个视频无法缓 ...
- 05_01_拉钩教育课程管理系统之一:项目介绍
任务一 项目介绍与后台系统搭建 1. 项目架构 1.1 项目介绍 拉钩教育后台管理系统,是提供给拉钩教育的相关业务人员使用的一个后台管理系统, 业务人员可以在这个后台管理系统中,对课程信息.讲师信 ...
- Python突破拉钩反爬机制,采集各类招聘数据
首先说一下这个有啥用?要说有用也没啥用,要说没用吧,既然能拿到这些数据,拿来做数据分析.能有效的得到职位信息,薪资信息等.也能为找工作更加简单吧,且能够比较有选择性的相匹配的职位及公司 很多人学习py ...
- Python selenium 拉钩爬虫
selenium 用作自动化测试工具,并非爬虫工具,用作爬虫性能没那么好.但既然可以读取网页信息,那还是可以用来爬取数据的.用该工具模拟访问,网站会认为是正常的访问行为. 项目创建几个文件,都在同一个 ...
- 使用python下载wallpaper Engine订阅的壁纸/视频
一.为什么想下载wallpaper Engine的壁纸 在游戏平台steam上,有一个壁纸软件wallpaper Engine,人称小红车,里面有各种好看的动态壁纸和视频,可以给我们的电脑设置动态 ...
- python pycrypto_Python使用PyCrypto实现AES加密功能示例
本文实例讲述了Python使用PyCrypto实现AES加密功能.分享给大家供大家参考,具体如下: #!/usr/bin/env python from Crypto.Cipher import AE ...
- 【Python】pyCryptodome模块实现AES加密、解密
高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用来替代原先的DES, ...
- .net aes加密视频等文件
公司学习平台在app端下载下来的视频需要加密 随查找资料参考一些写法 写了aes的加密方法 记录防止忘记 using System; using System.Collections.Generic; ...
- 一文看懂,python抓取m3u8里ts加密视频及合成、多线程、写入的问题
花了几天时间搞m3u8里的ts视频,还有多线程协程的处理问题.看了大量的回答,发现大多数人讲的都是个大概,具体的怎么用.什么原理没讲.今天就来带大家讲解怎么爬取m3u8里的加密ts视频. 目标网址我就 ...
最新文章
- Android开发之自动登录功能的实现
- Springmvc案例1----基于spring2.5的採用xml配置
- Android --- 调用MediaStore.Images.Media.insertImage保存图片时生成两张图片的问题
- python 3.5.2页面_Python 3.5.2实现websocket服务端
- Nginx基本数据结构之ngx_str_t
- a5 1c语言实现,初识C语言1_qq5fb3b05a5f322的技术博客_51CTO博客
- 如何使用Scylla进行OSINT信息收集
- python csv wordpress xmlrpc_wordpress_xmlrpc模块批量自动发布文章到wordpress - 老牛博客...
- jpg格式怎么转换成plt格式的_JPEG格式图片转PLT格式雕刻输出
- Acrel-2000Z智能电力监控系统解决方案
- 量化交易策略代码java_3.量化交易策略基本框架
- 30 个 Python 编程实用技巧
- c语言 随机四则运算,随机四则运算 C语言
- 在 Light Trail Adventures 中探索失落已久的复古未来沙漠城市
- 初学Flutter 环境搭建
- 台式计算机箱ip5x,IP5X防水是个什么概念?
- wap.php区别,WAP與PHP程序設計之基礎篇
- MyBatis中的日志(LOG4J)
- 完全卸载Myeclipse
- 矩阵特征多项式的系数公式