大家好,我是小小明。

最近看到几个视频网站的地址依然是m3u8格式,不禁有了使用python进行下载的想法,虽然下载m3u8格式视频的工具很多,但如果我们自行编码就能应对更多的情况。

关于m3u8的基础知识可以参考:Python实时下载B站直播间视频(M3U8视频流)

下面我们将使用Python下载m3u8格式的加密离线视频流。

游览器抓包过滤能够获取该影片的m3u8播放地址:

首先,测试一下该地址:

import m3u8headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
}playlist = m3u8.load(uri='https://vod8.wenshibaowenbei.com/20210628/g4yNLlI7/index.m3u8', headers=headers)
playlist.data
{'media_sequence': None,'is_variant': True,'is_endlist': False,'is_i_frames_only': False,'is_independent_segments': False,'playlist_type': None,'playlists': [{'uri': '/20210628/g4yNLlI7/1000kb/hls/index.m3u8','stream_info': {'program_id': 1,'bandwidth': 1000000,'resolution': '1280x720'}}],'segments': [],'iframe_playlists': [],'media': [],'keys': [],'rendition_reports': [],'skip': {},'part_inf': {},'session_data': [],'session_keys': []}

从结果看到,这是一个嵌套的地址。

所以写个方法解析真实地址:

import m3u8headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
}def get_real_url(url):playlist = m3u8.load(uri=url, headers=headers)return playlist.playlists[0].absolute_urireal_url = get_real_url('https://vod8.wenshibaowenbei.com/20210628/g4yNLlI7/index.m3u8')
real_url
'https://vod8.wenshibaowenbei.com/20210628/g4yNLlI7/1000kb/hls/index.m3u8'

解析真实地址的加密key:

playlist = m3u8.load(uri=real_url, headers=headers)
key = playlist.keys[-1]
print(key.uri, key.method, key.iv)
https://ts8.hhmm0.com:9999/20210628/g4yNLlI7/1000kb/hls/key.key AES-128 None

可以看到密钥下载地址和加密类型。

使用request下载密钥:

import requestsr = requests.get(playlist.keys[0].uri, headers=headers)
key = r.content
key
b'7ec5143edebbc899'

可以单线程直接下载视频:

import timen = len(playlist.segments)
size = 0
start = time.time()
for i, seg in enumerate(playlist.segments, 1):r = requests.get(seg.absolute_uri, headers=headers)data = r.contentdata = AESDecrypt(data, key=key, iv=key)size += len(data)with open("reusult.mp4", "ab") as f:f.write(data)print(f"\r下载进度({i}/{n}),已下载:{size/1024/1024:.2f}MB,下载已耗时:{time.time()-start:.2f}s", end=" ")
下载进度(1435/1435),已下载:424.69MB,下载已耗时:850s

单线程下载,好处是不会产生多余的文件,缺点是速度太慢了,一个视频下载了10多分钟。

下面我们整理一下完整的代码:

单线程视频下载的完整代码

import time
from Crypto.Util.Padding import pad
from Crypto.Cipher import AES
import requests
import m3u8headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
}def get_real_url(url):playlist = m3u8.load(uri=url, headers=headers)return playlist.playlists[0].absolute_uridef AESDecrypt(cipher_text, key, iv):cipher_text = pad(data_to_pad=cipher_text, block_size=AES.block_size)aes = AES.new(key=key, mode=AES.MODE_CBC, iv=key)cipher_text = aes.decrypt(cipher_text)return cipher_textdef download_m3u8_video(url, save_name):real_url = get_real_url(url)playlist = m3u8.load(uri=real_url, headers=headers)key = requests.get(playlist.keys[-1].uri, headers=headers).contentn = len(playlist.segments)size = 0start = time.time()for i, seg in enumerate(playlist.segments, 1):r = requests.get(seg.absolute_uri, headers=headers)data = r.contentdata = AESDecrypt(data, key=key, iv=key)size += len(data)with open(save_name, "ab" if i != 1 else "wb") as f:f.write(data)print(f"\r下载进度({i}/{n}),已下载:{size/1024/1024:.2f}MB,下载已耗时:{time.time()-start:.2f}s", end=" ")download_m3u8_video('https://vod8.wenshibaowenbei.com/20210628/g4yNLlI7/index.m3u8', '走进家门.mp4')

多线程下载改造

对于多线程,由于下载的文件可能出现间断,所以我们不能直接追加到目标视频中,可以先下载下来,最后统一合并并删除。

先创建ts视频下载的方法:

import os
import requestsdef download_ts(url, key, i):r = requests.get(url, headers=headers)data = r.contentdata = AESDecrypt(data, key=key, iv=key)with open(f"tmp/{i:0>5d}.ts", "ab") as f:f.write(data)print(f"\r{i:0>5d}.ts已下载", end="  ")if not os.path.exists("tmp"):os.mkdir('tmp')

任意下载一个片段测试一下:

import requests
import m3u8def get_real_url(url):playlist = m3u8.load(uri=url, headers=headers)return playlist.playlists[0].absolute_uriheaders = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
}
real_url = get_real_url('https://vod8.wenshibaowenbei.com/20210628/g4yNLlI7/index.m3u8')
playlist = m3u8.load(uri=real_url, headers=headers)
key = requests.get(playlist.keys[-1].uri, headers=headers).contentdownload_ts(playlist.segments[0].absolute_uri, key, 1)
00001.ts已下载

检查该片段可以正常播放。

然后执行以下方法即可10个线程同时一起下载:

from concurrent.futures import ThreadPoolExecutorwith ThreadPoolExecutor(max_workers=10) as pool:for i, seg in enumerate(playlist.segments):pool.submit(download_ts, seg.absolute_uri, key, i)

经过一分20秒左右的时间,所有视频流已经全部下载完毕,比单线程的速度快了不止10倍。

最后我们实现文件的合并和ts临时文件清除:

import globwith open('video.mp4', 'wb') as fw:files = glob.glob('tmp/*.ts')for file in files:with open(file, 'rb') as fr:fw.write(fr.read())print(f'\r{file}已合并!总数:{len(files)}', end="     ")os.remove(file)

执行后,已经在1秒左右时间合并并清除完临时文件。

多线程下载的完整代码

import glob
from concurrent.futures import ThreadPoolExecutor
import m3u8
import os
import requests
from Crypto.Util.Padding import pad
from Crypto.Cipher import AES
import requestsheaders = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
}def download_ts(url, key, i):r = requests.get(url, headers=headers)data = r.contentdata = AESDecrypt(data, key=key, iv=key)with open(f"tmp/{i:0>5d}.ts", "ab") as f:f.write(data)print(f"\r{i:0>5d}.ts已下载", end="  ")def get_real_url(url):playlist = m3u8.load(uri=url, headers=headers)return playlist.playlists[0].absolute_uridef AESDecrypt(cipher_text, key, iv):cipher_text = pad(data_to_pad=cipher_text, block_size=AES.block_size)aes = AES.new(key=key, mode=AES.MODE_CBC, iv=key)cipher_text = aes.decrypt(cipher_text)return cipher_textdef download_m3u8_video(url, save_name, max_workers=10):if not os.path.exists("tmp"):os.mkdir('tmp')real_url = get_real_url(url)playlist = m3u8.load(uri=real_url, headers=headers)key = requests.get(playlist.keys[-1].uri, headers=headers).contentwith ThreadPoolExecutor(max_workers=max_workers) as pool:for i, seg in enumerate(playlist.segments):pool.submit(download_ts, seg.absolute_uri, key, i)with open(save_name, 'wb') as fw:files = glob.glob('tmp/*.ts')for file in files:with open(file, 'rb') as fr:fw.write(fr.read())print(f'\r{file}已合并!总数:{len(files)}', end="     ")os.remove(file)download_m3u8_video('https://vod8.wenshibaowenbei.com/20210628/g4yNLlI7/index.m3u8', '走进家门.mp4')

Python下载M3U8加密视频示例相关推荐

  1. python爬取下载m3u8加密视频,原来这么简单!

    1.前言 爬取视频的时候发现,现在的视频都是经过加密(m3u8),不再是mp4或者avi链接直接在网页显示,都是经过加密形成ts文件分段进行播放. 今天就教大家如果通过python爬取下载m3u8加密 ...

  2. 下载m3u8加密视频的一些经验和小细节

    这里有一个神器,使用非常方便,不用看下边的了 链接 一.下载ts分片 1.桌面上建立一个文件夹 2.下载index.m3u8,查看多少个ts分片 3.idm下载ts分片到该文件夹 4.复制刚才的ind ...

  3. python下载m3u8视频_使用python 下载m3u8格式视频,并使用ffmpeg 合成视频

    使用python 下载m3u8格式视频,并合成 # -*- coding: utf-8 -*- # Created on 2018/07/26 import os import requests &q ...

  4. 关于如何下载m3u8加密视频

    本例的key文件较简单(即 :可下载并查看文件内容),若遇到再编码的key文件,需要另外解析 一.下载.ts视频文件.m3u8文件.key文件 简单一点说m3u8加密技术就是将原视频分割成n个.ts文 ...

  5. python编程实例视屏-python 下载抖音视频示例源码

    [实例简介] 下载抖音视频 [实例截图] [核心代码] #code:utf-8 import requests from bs4 import BeautifulSoup import json se ...

  6. blob的真实地址怎么获得_使用Python抓取m3u8加密视频 续:获得index.m3u8 地址

    之前写<使用Python抓取m3u8加密视频>笔记的原因,是自己有几个视频想保存,但对于m3u8, .ts 文件拼接不熟悉,就尝试写个脚本练手. 今天看了回复,有同学想知道如何从视频网站上 ...

  7. python 爬取加密视频_使用Python抓取m3u8加密视频 续:获得index.m3u8 地址

    之前写<使用Python抓取m3u8加密视频>笔记的原因,是自己有几个视频想保存,但对于m3u8, .ts 文件拼接不熟悉,就尝试写个脚本练手. 今天看了回复,有同学想知道如何从视频网站上 ...

  8. python下载大文件mp4_Python 下载 m3u8 格式视频

    Python requests 下载 m3u8 格式 视频 最近爬取一个视频网站,遇到 m3u8 格式的视频需要下载. 抓包分析,视频文件是多个 ts 文件,什么是 ts文件,请去百度吧: 附图:抓包 ...

  9. python多线程下载视频_python 实现多线程下载m3u8格式视频并使用fmmpeg合并

    电影之类的长视频好像都用m3u8格式了,这就导致了多线程下载视频的意义不是很大,都是短视频,线不线程就没什么意义了嘛. 我们知道,m3u8的链接会下载一个文档,相当长,半小时的视频,应该有接近千行ts ...

最新文章

  1. android layout analyze
  2. “金财工程”网络安全 五
  3. 【译】What do machine learning practitioners actually do?
  4. ITK:提取网格边界上的顶点
  5. python3键盘事件_python+selenium3 鼠标事件和键盘事件
  6. 满意度调查access模板_洪安镇推进综合便民服务中心标准化建设,着力提升群众满意度...
  7. ### C++总结-[类成员函数]
  8. python字典items返回什么_Python 字典items返回列表,iteritems返回迭代器
  9. 2_C语言中的数据类型 (六)浮点数
  10. RedHat Enterprise Linux 5下安装firefox
  11. 鸿蒙os framework,疯壳-鸿蒙OS-HDF驱动框架
  12. 计算机技术与园林,计算机技术在园林绿化设计中的应用
  13. 《统计会犯错——如何避免数据分析中的统计陷阱》导读
  14. 怎样使用Scanner(扫描仪),超级详细,不容错过!!!
  15. c语言中get的作用,c语言中get的用法
  16. [ZGC升级记录](to-space exhausted/Evacuation Failure)
  17. 《21世纪的书:信息时代商业思想10×10阅读》書目信息
  18. P1867 【Mc生存】经验值 java题解
  19. 如何用科学的方法,保障数据准确性
  20. 技术的共通性—从姿态估计到自动驾驶

热门文章

  1. JavaScript - WebAPI - 案例 - 点名系统/打地鼠/计时器/今日代办
  2. 小乌龟git如何同步远程分支_GitLab结合Git小乌龟实现不同代码分支合并
  3. HCIE之路-11 华为路由引入,路由控制基础思维导图(不定期更新,纯个人理解,欢迎批评指正!!!)
  4. C语言中scanf输入汇总
  5. linux中bash命令占用内存高,最牛B的 Linux Shell 命令 系列连载(三)
  6. Google Earth Engine(GEE)——全球土壤生物气候变量数据集
  7. sdcms php版手册,目录结构及说明
  8. 哪几款降噪耳机佩戴舒适?佩戴舒适的降噪耳机排行
  9. c 连接mysql批量存储数据库_C语言连接操作MySQL数据库的方法
  10. css设置背景透明度,css设置背景透明度 你需要学习了