日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python 下载拉钩教育AES加密视频

發布時間:2024/4/11 python 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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.現在已經知道請求的地址,然后我們就可以發送請求,再解析數據了?,F在有許多的視頻網站,都是通過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加密视频的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。