python 爬蟲 m3u8 視頻文件 加密解密 整合mp4

文章目錄

    • 一、完整代碼
    • 二、視頻分析
      • 1. 認識m3u8文件
      • 2. 獲取密鑰,構建解密器
      • 3. 下載ts文件
      • 4. 合并ts文件為mp4
    • 三、總結

一、完整代碼

完整代碼如下:

import requests
import re
import os
from tqdm import tqdm
from Crypto.Cipher import AES# 創建臨時文件夾
dirs = 'ts_list_need_to_merge/'
os.makedirs(dirs, exist_ok=True)headers = {'Accept': '*/*','Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6','Connection': 'keep-alive','Origin': 'http://www.kpd510.me','Referer': 'http://www.kpd510.me/','Sec-Fetch-Dest': 'empty','Sec-Fetch-Mode': 'cors','Sec-Fetch-Site': 'cross-site','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.69','sec-ch-ua': '"Chromium";v="116", "Not)A;Brand";v="24", "Microsoft Edge";v="116"','sec-ch-ua-mobile': '?0','sec-ch-ua-platform': '"Windows"',}def parse_m3u8_text(m3u8_text):m3u8_text = m3u8_text.split()encode_info = [line for line in m3u8_text if line.startswith('#EXT-X-KEY:')][0]pattern = r"#EXT-X-KEY:METHOD=(.*),URI=\"(.*)\""  ## 獲得加密method 和 key.key的urlmatch = re.search(pattern, encode_info)if match:method = match.group(1)key_url = match.group(2)else:raise '解析失敗'## 獲得ts文件urlts_list = [line for line in m3u8_text if line.endswith('ts')]return method, key_url, ts_listdef download_method_1(ts_list):# 這里弄一個filename_list 方便后續合并ts到mp4ts_file_list = []for ts_url in tqdm(ts_list):filename = dirs + os.path.split(ts_url)[-1]content = requests.get(ts_url, headers=headers).contentdecrypt_content_and_save_file(filename, content)ts_file_list.append(filename)return ts_file_listdef decrypt_content_and_save_file(filename, content):with open(filename, mode='wb') as f:f.write(decrypter.decrypt(content))def merge_ts_to_mp4(filename, ts_file_list):with open(filename, mode='ab') as f1:for ts_file in ts_file_list:with open(ts_file, mode='rb') as f2:f1.write(f2.read())if __name__ == '__main__':m3u8_url = 'https://play.bo262626.com/20231108/xV1bY9Cn/700kb/hls/index.m3u8'response = requests.get(m3u8_url, headers=headers)m3u8 = response.textmethod, key_url, ts_list = parse_m3u8_text(m3u8)key_url = 'https://play.bo262626.com' + key_urlts_list = ['https://play.bo262626.com' + item for item in ts_list]key = requests.get(key_url, headers=headers).contentdecrypter = AES.new(key, AES.MODE_CBC)ts_file_list = download_method_1(ts_list[:3])merge_ts_to_mp4('test.mp4', ts_file_list)

二、視頻分析

1. 認識m3u8文件

m3u8的結構詳細分析可以看這個鏈接m3u8 文件格式詳解 - 簡書 (jianshu.com),這里我們只簡要介紹一下;

相信無論多小白都應該知道如何打開開發者模型解析得到下面的結果;

要注意的是,只有預覽里面包含了ts信息的才算是我們需要的m3u8文件;大家可以看到左側有兩個index.m3u8,其中一個是沒有ts信息的,所以我們直接忽略掉;現在我們先下載來,再來具體分析一下m3u8文件以及里面的內容分別表達什么意思;

下載代碼如下:

import requests
import reheaders = {'Accept': '*/*','Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6','Connection': 'keep-alive','Origin': 'http://www.kpd510.me','Referer': 'http://www.kpd510.me/','Sec-Fetch-Dest': 'empty','Sec-Fetch-Mode': 'cors','Sec-Fetch-Site': 'cross-site','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.69','sec-ch-ua': '"Chromium";v="116", "Not)A;Brand";v="24", "Microsoft Edge";v="116"','sec-ch-ua-mobile': '?0','sec-ch-ua-platform': '"Windows"',
}response = requests.get('https://play.bo262626.com/20231108/xV1bY9Cn/700kb/hls/index.m3u8', headers=headers)m3u8 = response.text

m3u8文件的實質是一個視頻的url列表,其中ts是計算器可以直接播放的視頻格式文件,但是直接下載是可能被加了密的文件,我們需要m3u8文件內容信息進行解密;

我們可以這樣理解,m3u8把一個完整的mp4視頻切割成了很多的小塊,每一個小塊在m3u8都是ts文件格式,并在m3u8中采取了加密的措施,至于為什么要加密,這里就不多介紹;

在一般的視頻爬取中,我們只需要考慮兩個部分,一個是EXT-X-KEY,一個是ts

其中EXT-X-KEY包含了ts的加密方式,ts包含了ts文件的下載地址;

在紅色部分也就是EXT-X-KEY部分,我們可以從METHOD中獲取到采取的加密方式是AES-128,同時看到URI的地址/20231126/10VkaJks/700kb/hls/key.key,這也就是AES加密密匙的地址:key.key,接下來我們寫一個文件來對m3u8文件解析,目的是提取出紅色部分和藍色部分;

代碼如下:

def parse_m3u8_text(m3u8_text):m3u8_text = m3u8_text.split()encode_info = [line for line in m3u8_text if line.startswith('#EXT-X-KEY:')][0]pattern = r"#EXT-X-KEY:METHOD=(.*),URI=\"(.*)\""  ## 獲得加密method 和 key.key的urlmatch = re.search(pattern, encode_info)if match:method = match.group(1)key_url = match.group(2)else:raise '解析失敗'## 獲得ts文件urlts_list = [line for line in m3u8_text if line.endswith('ts')]return method, key_url, ts_list## 在這里我們直接把m3u8文本丟進去就可以獲得
## method, key_url, ts_list
method, key_url, ts_list = parse_m3u8_text(m3u8)
## method = 'AES-128'
## key_url = '/20231108/xV1bY9Cn/700kb/hls/key.key'
## ts_list = ['...ts', '...ts', ...]

2. 獲取密鑰,構建解密器

因為構建解密器我們需要密鑰,而密鑰存儲在key.key中,首先我們需要解析key_url獲取密鑰;

在這里可以明顯的看到key_url = '/20231108/xV1bY9Cn/700kb/hls/key.key'這不是一個完整的url,我們在這里加上獲取m3u8請求的主域名便好;

代碼如下:

headers = {'Accept': '*/*','Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6','Connection': 'keep-alive','Origin': 'http://www.kpd510.me','Referer': 'http://www.kpd510.me/','Sec-Fetch-Dest': 'empty','Sec-Fetch-Mode': 'cors','Sec-Fetch-Site': 'cross-site','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.69','sec-ch-ua': '"Chromium";v="116", "Not)A;Brand";v="24", "Microsoft Edge";v="116"','sec-ch-ua-mobile': '?0','sec-ch-ua-platform': '"Windows"',
}key_url = 'https://play.bo262626.com' + key_url
key = requests.get(key_url, headers=headers).content
# 這里我們得到key = b'388d590fabfeabcf' 是一個二進制結果

得到了密鑰,再結合加密方式AES-128,我們就可以構建一個解密器,構建解密器代碼如下:

from Crypto.Cipher import AES
## 這里網絡爬取視頻一般是MODE_CBC模式
decrypter = AES.new(key, AES.MODE_CBC)

這里要提起的是網絡上的m3u8文件采取的加密一般是AES.MODE_CBC模式,在后續操作中如果這里出問題就換MODE一個一個試就好;

3. 下載ts文件

由于有許多的ts文件,我們有三種方法,第一是簡單的requests請求一個一個下,這也是最費時的一種;第二個是多進程或者多線程的方式下載;第三個是采用協程的方式;接下來我們一個個實現;

在開始之間,ts_list存在同樣的問題,就是需要重構url,這里代碼如下:

ts_list = ['https://play.bo262626.com' + item for item in ts_list]# 這里得到:
# ['https://play.bo262626.com/20231108/xV1bY9Cn/700kb/hls/o3jSJ9mc.ts',
#  'https://play.bo262626.com/20231108/xV1bY9Cn/700kb/hls/GNHDlClJ.ts',
#  'https://play.bo262626.com/20231108/xV1bY9Cn/700kb/hls/zKym5c6V.ts',
#  'https://play.bo262626.com/20231108/xV1bY9Cn/700kb/hls/4ll4NQH3.ts',
#  'https://play.bo262626.com/20231108/xV1bY9Cn/700kb/hls/RwUOniSQ.ts' ...]

再測試一下解密器是否可以:

def decrypt_content_and_save_file(filename, content):with open(filename, mode='wb') as f:f.write(decrypter.decrypt(content))test_content = requests.get(ts_list[0], headers=headers).content
decrypt_content_and_save_file('test.ts', test_content)## 打開視頻看是否能打開
## 如果能打開說明解密沒問題

直接requests: 代碼如下

import os
from tqdm import tqdmdirs = 'ts_list_need_to_merge/'
os.makedirs(dirs, exist_ok=True)def download_method_1(ts_list):# 這里弄一個filename_list 方便后續合并ts到mp4ts_file_list = []for ts_url in tqdm(ts_list):filename = dirs + os.path.split(ts_url)[-1]content = requests.get(ts_url, headers=headers).contentdecrypt_content_and_save_file(filename, content)ts_file_list.append(filename)return ts_file_list# 下載測試
ts_file_list = download_method_1(ts_list[:4])

實現挺慢的,不合理;

多進程: 代碼如下

# 忘記了,有時間再回來實現

協程: 代碼如下

# 忘記了,有時間再回來實現

4. 合并ts文件為mp4

在完成前面的步驟后,直接ab的方式把所有的文件按順序加入就好;

def merge_ts_to_mp4(filename, ts_file_list):with open(filename, mode='ab') as f1:for ts_file in ts_file_list:with open(ts_file, mode='rb') as f2:f1.write(f2.read())merge_ts_to_mp4('test.mp4', ts_file_list)

后續如果需要刪除'ts_list_need_to_merge/'這個臨時文件夾里面的所有內容,直接運行下面代碼

import send2trashsend2trash.send2trash('ts_list_need_to_merge/') # send2trash.send2trash(dirs)

三、總結

別在圖書館測試這段代碼!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/215899.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/215899.shtml
英文地址,請注明出處:http://en.pswp.cn/news/215899.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Shopify二次開發之五:元字段(Metafields)

目錄 解釋 操作 1、添加Custom data 2、選擇特定類型的數據 3、為Page配置元子段和值 4、模板訪問 解釋 Shopify Metafields 是一種用于存儲和管理自定義數據的功能。它們允許商戶在商城中的產品、訂單、客戶、Page等對象上添加自定義字段,以滿足特定業務需求…

c語言->自定義類型聯合體和枚舉類型

系列文章目錄 文章目錄 前言 ?作者簡介:大家好,我是橘橙黃又青,一個想要與大家共同進步的男人😉😉 🍎個人主頁:橘橙黃又青_C語言,函數,指針-CSDN博客 目的:學習聯合體和枚舉類型的…

[cleanrl] ppo_continuous_action源碼解析

1 import庫(略) import os import random import time from dataclasses import dataclassimport gymnasium as gym import numpy as np import torch import torch.nn as nn import torch.optim as optim import tyro from torch.distributions.normal…

Kubernetes實戰(八)-防止k8s namespace被誤刪除

1 背景 運維新同學在預發環境操作刪除pod的時候,不知道什么原因把kubectl delete pod命令敲成了kubectl delete ns pre把預發環境刪了,幾十個模塊,將近一個小時才恢復。幸虧是測試環境啊,如果是生產可以可以跑路了。 2 解決方案…

jsonpath:使用Python處理JSON數據

使用Python處理JSON數據 25.1 JSON簡介 25.1.1 什么是JSON JSON全稱為JavaScript Object Notation,一般翻譯為JS標記,是一種輕量級的數據交換格式。是基于ECMAScript的一個子集,采用完全獨立于編程語言的文本格式來存儲和表示數據。簡潔和清…

java對二維數組進行排序

一、按行排序&#xff1a; 對二維數組按進行排序&#xff0c;直接調用Arrays.sort就行&#xff1a; private static int [][] sortRows(int[][] arr) {//行排序for (int i 0; i < arr.length; i) {Arrays.sort(arr[i]);}return arr;}二、按列排序&#xff1a; 1.使用比較…

計算機網絡:應用層(一)

我最近開了幾個專欄&#xff0c;誠信互三&#xff01; > |||《算法專欄》&#xff1a;&#xff1a;刷題教程來自網站《代碼隨想錄》。||| > |||《C專欄》&#xff1a;&#xff1a;記錄我學習C的經歷&#xff0c;看完你一定會有收獲。||| > |||《Linux專欄》&#xff1…

鴻蒙開發之狀態管理@Observed和@ObjectLink

一、使用場景 當對象內引用對象&#xff0c;改變內部對象屬性的時候其他狀態管理如State、Provide、Consume等是無法觸發更新的。同樣&#xff0c;在數組內如果有對象&#xff0c;改變對象的屬性也是無法更新的。在這種情況下就可以采用Observed和ObjectLink裝飾器了。 二、使…

C# WPF上位機開發(簡易圖像處理軟件)

【 聲明&#xff1a;版權所有&#xff0c;歡迎轉載&#xff0c;請勿用于商業用途。 聯系信箱&#xff1a;feixiaoxing 163.com】 圖像處理是工業生產重要的環節。不管是定位、測量、檢測還是識別&#xff0c;圖像處理在工業生產中扮演重要的角色。而c#由于自身快速開發的特點&a…

玩轉 Go 語言并發編程:Goroutine 實戰指南

一、goroutine 池 本質上是生產者消費者模型在工作中我們通常會使用可以指定啟動的 goroutine 數量-worker pool 模式&#xff0c;控制 goroutine 的數量&#xff0c;防止 goroutine 泄漏和暴漲一個簡易的 work pool 示例代碼如下&#xff1a; package mainimport ("fmt…

小程序跳轉tabbar,tabbar頁面不刷新

文章地址&#xff1a;12.小程序 之切換到tabBar頁面不刷新問題_360問答 解決辦法備份&#xff1a; wx.switchTab&#xff1a;跳轉到 tabBar 頁面&#xff0c;并關閉其他所有非 tabBar 頁面 wx.reLaunch&#xff1a;關閉所有頁面&#xff0c;打開到應用內的某個頁面。 wx.reLa…

解決微信小程序中 ‘nbsp;‘ 空格不生效的問題

在微信小程序開發中&#xff0c;我們經常會使用 來表示一個空格。這是因為在 HTML 中&#xff0c;空格會被解析為一個普通字符&#xff0c;而不會產生實際的空白間距。而 是一種特殊的字符實體&#xff0c;它被解析為一個不可見的空格&#xff0c;可以在頁面上產生真正的空…

力扣70. 爬樓梯

動態規劃 思路&#xff1a; 使用遞歸比較容易理解&#xff0c; f(n) f(n - 1) f(n - 2)&#xff1b; 到剩余1級臺階有 f(n - 1)&#xff0c;到剩余2級臺階有 f(n-2)&#xff1b;邊界情況是 n 0, f(0) 1n 1, f(1) 1n 2, f(2) 2 遞歸代碼實現&#xff1a; class Soluti…

Axure RP 9 入門教程

1. Axure簡介 Axure 是一個交互式原型設計工具&#xff0c;可以幫助用戶創建復雜的交互式應用程序和網站。Axure 能夠讓用戶快速構建出具有高度可交互性的原型&#xff0c;可以在團隊中進行協作、分享和測試。 使用 Axure 可以設計出各種不同類型的原型&#xff0c;包括網站、移…

系列十五、搭建redis集群

一、概述 上篇文章介紹了redis集群的相關知識&#xff0c;本章實戰演示redis的集群環境的詳細搭建步驟。如果幫助到了你&#xff0c;請點贊 收藏 關注&#xff01;有疑問的話也可以評論區交流。 二、搭建步驟 2.1、預備知識 判斷一個集群中的節點是否可用&#xff0c;是集群…

【SpringBoot篇】詳解基于Redis實現短信登錄的操作

文章目錄 &#x1f970;前言&#x1f6f8;StringRedisTemplate&#x1f339;使用StringRedisTemplate?常用的方法 &#x1f6f8;為什么我們要使用Redis代替Session進行登錄操作&#x1f386;具體使用?編寫攔截器?配置攔截器&#x1f33a;基于Redis實現發送手機驗證碼操作&am…

EarCMS 前臺任意文件上傳漏洞復現

0x01 產品簡介 EarCMS是一個APP內測分發系統的平臺。 0x02 漏洞概述 EarCMS前臺put_upload.php中,存在pw參數硬編碼問題,同時sql語句pdo使用錯誤,沒有有效過濾sql語句,可以控制文件名和后綴,導致可以任意文件上傳。 0x03 復現環境 FOFA:app="EearCMS" 0x0…

Flutter實現自定義二級列表

在Flutter開發中&#xff0c;其實系統已經給我們提供了一個可靠的二級列表展開的API&#xff08;ExpansionPanelList&#xff09;&#xff0c;我們先看系統的二級列表展開效果&#xff0c;一次只能展開一個&#xff0c;用ExpansionPanelList.radio實現 由此可見&#xff0c;已經…

容器化升級對服務有哪些影響?

容器技術是近幾年計算機領域的熱門技術&#xff0c;特別是隨著各種云服務的發展&#xff0c;越來越多的服務運行在以 Docker 為代表的容器之內。 本文我們就來分享一下容器化技術相關的知識。 容器化技術簡介 相比傳統虛擬化技術&#xff0c;容器技術是一種更加輕量級的操作…

分治法求最大子列和

給定N個整數的序列{ A1, A2, …, AN}&#xff0c;其中可能有正數也可能有負數&#xff0c;找出其中連續的一個子數列&#xff08;不允許空序列&#xff09;&#xff0c;使它們的和盡可能大&#xff0c;如果是負數&#xff0c;則返回0。使用下列函數&#xff0c;完成分治法求最大…