【爬虫】九、综合案例之m3u8文件

2023-11-14

视频网站常规处理方法:
用户上传视频–>转码(处理视频)–>切片处理(把单个文件进行拆分,一般把拆分好的文件放到M3U8、txt、json的文本中),用户在拖动进度条时则进入到某个分片中。
需要一个文件记录:
1.视频播放顺序。
2.视频存放路径。
在这里插入图片描述

1 爬取m3u8,简单版

抓取视频的方法:
1.找到M3U8文件(可能会被隐藏)。
2.通过M3U8下载ts文件。
3.可以通过各种手段(可以为非编程手段)把ts文件合并为一个mp4文件。

#爬取影院,简单版
import requests
import re
import asyncio
import aiohttp
import aiofiles
import os
from tqdm import tqdm

 #ts文件所在的地址
url = 'm3u8文件的url'
ulrMain = url.rsplit('/', 1)[0]
async def getM3U8(url):
    resp = requests.get(url)
    resp.encoding = "utf-8"
    obj = re.compile(r',(?P<ts>.*?)#',re.S)
    tsList = obj.finditer(resp.text)
    resp.close()
    tasks = []
    for ts in tsList:
        ts = ts.group("ts").strip()
        tasks.append(asyncio.create_task(getTsFile(ts)))
    await asyncio.wait(tasks)


async def getTsFile(ts):
    tsUrl = ulrMain + '/' + ts
    async with aiohttp.ClientSession() as session:
        async with session.get(tsUrl) as resp:
            async with aiofiles.open('attachment/kuangbiao/' + ts, mode='wb') as f:
                await f.write(await resp.content.read())
    print(ts," ok!")

def get_video():
    files = os.listdir('attachment/kuangbiao/')
    for file in tqdm(files, desc="正在转换视频格式:"):
        if os.path.exists('attachment/kuangbiao/' + file):
            with open('attachment/kuangbiao/' + file, 'rb') as f1:
                with open('attachment/kuangbiao/' + "第一集.mp4", 'ab') as f2:
                    f2.write(f1.read())
        else:
            print("失败")

if __name__ == '__main__':
    # asyncio.run(getM3U8(url))
    get_video()

2 爬取m3u8,复杂版

思路:
1.拿到主页的页面源代码,找到iframe
iframe 元素会创建包含另外一个文档的内联框架(即行内框架),即在一个html中通过iframe标签可以引入另外的html。取iframe里的src可以得到视频播放的html,在sources中由页面源代码。
在这里插入图片描述
在这里插入图片描述

2.从iframe的页面源代码中拿到m3u8文件。
在这里插入图片描述
3.下载第一层m3u8文件–>下载第二层m3u8文件(视频存放路径)
4.下载视频即ts文件
5.下载密钥,进行解密
6.合并所有的ts文件为一个mp4文件

#爬取视频(复杂版)

"""
思路:
1.拿到主页的页面源代码,找到iframe
2.从iframe的页面源代码中拿到m3u8文件
3.下载第一层m3u8文件-->下载第二层m3u8文件(视频存放路径)
4.下载视频即ts文件
5.下载密钥,进行解密
6.合并所有的ts文件为一个mp4文件
"""

import requests
import re
import asyncio
import aiohttp
import aiofiles
import os
from tqdm import tqdm
from concurrent.futures import ThreadPoolExecutor
from Cryptodome.Cipher import AES
import brotli

async def getMainM3u8Url(url):
    resp = requests.get(url)
    with open("attachment/page.txt","wb","utf-8") as f:
        f.write(resp.text)
    print(resp.text)
    obj = re.compile('var player_aaaa=.*?"url":"(?P<indexUrl>.*?)","url_next":"(?P<nextUrl>.*?)","from"',re.S)
    urlList = obj.search(resp.text)
    resp.close()
    indexUrl = str(urlList.group("indexUrl")).replace("\\",'')
    print(indexUrl)
    return indexUrl


async def getM3u8Key(indexUrl):
    async with aiofiles.open("attachment/狂飙第一集m3u8.txt", "r") as f:
        async for line in f:
            if line.startswith("#EXT-X-KEY:"):
                keyUrl = str(line).split('"',2)[1]
                print(keyUrl)
                break
                #'Accept - Encoding': 'gzip, deflate, br',

    headers = {
        'Accept': '* / *',
        'Accept - Language': 'zh - CN, zh;q = 0.9',
        'Cache - Control': 'no - cache',
        'Connection': 'keep - alive',
        'Host': 'hnzy.bfvvs.com',
        'Origin': 'https: // m3.sanmitt.cn',
        'Pragma': 'no - cache',
        'sec - ch - ua': '"Chromium";v = "110", "Not A(Brand";v = "24", "Google Chrome";v = "110"',
        'sec - ch - ua - mobile': '?0',
        'sec - ch - ua - platform': '"Windows"',
        '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/110.0.0.0 Safari/537.36'
    }
    resp = requests.get(keyUrl,headers = headers)
    return resp.content

async def getM3u8File(indexUrl):
    resp = requests.get(indexUrl)
    resp.encoding = "utf-8"
    async with aiofiles.open("attachment/狂飙第一集m3u8.txt","wb") as f1:
        await f1.write(resp.content)
    resp.close()
    tasks = []
    async with aiohttp.ClientSession() as session:   #提前创建一个session,就不需要每下载一个ts文件都需要创建
        async with aiofiles.open("attachment/狂飙第一集m3u8.txt","r") as f2:
            async for line in f2:
                if line.startswith("#"):
                    continue
                tsUrl = line.strip()
                print(tsUrl)
                tasks.append(asyncio.create_task(getTsFile(tsUrl,session)))
            await asyncio.wait(tasks)

async def getTsFile(tsUrl,session):
    name = tsUrl.split("-",1)[1]
    async with session.get(tsUrl) as resp:
        async with aiofiles.open('attachment/second/' + name, mode='wb') as f:
            await f.write(await resp.content.read())
    print(name," ok!")

async def decodeTs(key):
    tasks = []
    async with aiofiles.open("attachment/狂飙第一集m3u8.txt", "r") as f2:
        async for line in f2:
            if line.startswith("#") or line.startswith(" "):
                continue
            name = (line.strip()).split("-",1)[1]
            # print(name)
            # 开始创建异步任务
            tasks.append(asyncio.create_task(decodeByKey(name, key)))
        await asyncio.wait(tasks)


async def decodeByKey(fileName, key):
    #解密,在M38U文件中可以看到加密方式为AES
    aes = AES.new(key=key, mode=AES.MODE_CBC, IV=b"0000000000000000")
    async with aiofiles.open(f"attachment/second/{fileName}","rb") as f1:
        async with aiofiles.open(f"attachment/first/temp_{fileName}","wb") as f2:
            bs = await f1.read()
            await f2.write(aes.decrypt(bs))
    print(f"{fileName} is ok")


async def get_video():
    files = os.listdir('attachment/first/')
    for file in tqdm(files, desc="正在转换视频格式:"):
        if os.path.exists('attachment/first/' + file):
            async with aiofiles.open('attachment/first/' + file, 'rb') as f1:
                async with aiofiles.open('attachment/first/' + "第二集.mp4", 'ab') as f2:
                    await f2.write(await f1.read())
        else:
            print("失败")

async def main(url):
    indexUrl = 'm3u8文件的url'
    # 1.拿到主页的页面源代码,找到iframe
    # 2.从iframe的页面源代码中拿到m3u8文件
    # indexUrl = await getMainM3u8Url(url)

    # 3.下载第一层m3u8文件 -->下载第二层m3u8文件(视频存放路径)
    # await getM3u8File(indexUrl)
    # 4.下载视频即ts文件

    # 5.下载密钥,进行解密
    key = await getM3u8Key(indexUrl)
    await decodeTs(key)
    # 6.合并所有的ts文件为一个mp4文件
    await get_video()

if __name__ == '__main__':
    url = '视频网页地址'
    asyncio.run(main(url))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【爬虫】九、综合案例之m3u8文件 的相关文章

  • 使用 Python 编辑 RTF 文件

    也许这是一个愚蠢的问题 但我不明白 所以道歉 我有一个 RTF 文档 我想更改它 例如 有一个表 我想复制一行并以面向对象的方式更改代码中第二行中的文本 我认为 pyparsing 应该是可行的方法 但我摆弄了几个小时但没有明白 我没有提供
  • Python 和 Numpy 是 nan 和 set

    我在使用 Python 的 Numpy set 和 NaN 非数字 时遇到了不可预测的行为 gt gt gt set np float64 nan np float64 nan set nan nan gt gt gt set np flo
  • Flask中使用的路由装饰器是如何工作的

    我熟悉 Python 装饰器的基础知识 但是我不明白这个用于 Flask 路由的特定装饰器是如何工作的 以下是 Flask 网站上的代码片段 from flask import Flask escape request app Flask
  • 定义Python源代码编码的正确方法

    PEP 263 http www python org dev peps pep 0263 定义如何声明Python源代码编码 通常 Python 文件的前两行应以以下内容开头 usr bin python coding
  • 如何使用 python 的 http.client 准确读取一个响应块?

    Using http client在 Python 3 3 或任何其他内置 python HTTP 客户端库 中 如何一次读取一个分块 HTTP 响应一个 HTTP 块 我正在扩展现有的测试装置 使用 python 编写 http clie
  • 将 C++ 指针作为参数传递给 Cython 函数

    cdef extern from Foo h cdef cppclass Bar pass cdef class PyClass cdef Bar bar def cinit self Bar b bar b 这总是会给我类似的东西 Can
  • 为什么第二个 request.session cookies 返回空?

    我想使用 requests Session post 登录网站 但是当我已经登录主页 然后进入帐户页面时 看来cookies还没有保存 因为cookies是空的 而且我无法进入正确的帐户页面 import requests from bs4
  • 如何获取numpy.random.choice的索引? - Python

    是否可以修改 numpy random choice 函数以使其返回所选元素的索引 基本上 我想创建一个列表并随机选择元素而不进行替换 import numpy as np gt gt gt a 1 4 1 3 3 2 1 4 gt gt
  • 将 pandas 剪切操作转换为常规字符串

    我明白了 pandas cut 操作的输出 0 0 20 1 0 20 2 0 20 3 0 20 4 0 20 5 0 20 6 0 20 7 0 20 8 0 20 9 0 20 如何将 0 20 转换为 0 20 我正在这样做 str
  • 是否有一个包可以维护所有带有符号的货币列表?

    是否有一个 python 包提供所有 或相当完整 货币的列表与符号 如美元的 有优秀的pycountry 贪财的 https github com limist py moneyed and ccy http code google com
  • PIL.Image.open和tf.image.decode_jpeg返回值的区别

    我使用 PIL Image open 和 tf image decode jpeg 将图像文件解析为数组 但发现PIL Image open 中的像素值与tf image decode jpeg不一样 为什么会出现这种情况 Thanks 代
  • 使用标签或 href 传递 Django 数据

    我有一个包含链接的表 当单击该链接进行更多操作时 我想将一些数据传递给我的函数 my html table tbody for query in queries tr td value a href internal my func que
  • 为什么在Python解释器中输入_会返回True? [复制]

    这个问题在这里已经有答案了 我的翻译行为非常奇怪 gt gt gt True gt gt gt type True
  • App Engine 实体到字典

    将 google app engine 实体 在 python 中 复制到字典对象的好方法是什么 我正在使用 db Expando 对象 所有属性均为扩展属性 Thanks 有一个名为foo尝试 foo dict
  • Flask 应用程序路由中的多个参数

    烧瓶怎么写app route如果我在 URL 调用中有多个参数 这是我从 AJax 调用的 URL http 0 0 0 0 8888 createcm summary VVV change Feauure 我试图写我的烧瓶app rout
  • 如何在 Seaborn 中的热图轴上表达类

    我使用 Seaborn 创建了一个非常简单的热图 显示相似性方阵 这是我使用的一行代码 sns heatmap sim mat linewidths 0 square True robust True sns plt show 这是我得到的
  • 基于值而不是类型的单次调度

    我在 Django 上构建 SPA 并且有一个庞大的功能 其中包含许多功能if用于检查我的对象字段的状态名称的语句 像这样 if self state new do some logic if self state archive do s
  • 在 numpy 中连接维度

    我有x 1 2 3 4 5 6 7 8 9 10 11 12 shape 2 2 3 I want 1 2 3 4 5 6 7 8 9 10 11 12 shape 2 6 也就是说 我想连接中间维度的所有项目 在这种特殊情况下我可以得到这
  • 寻找完美的正方形

    我有这个Python代码 def sqrt x ans 0 if x gt 0 while ans ans lt x ans ans 1 if ans ans x print x is not a perfect square return
  • django jet 中的自定义徽标

    我目前正在尝试对 django 管理面板的皮肤进行一些定制 以使其更符合我们的品牌 目前我们使用 django jet 来美化管理面板 django jet 可以自定义 css html 吗 所有评论都说我应该更改一些 html 文件 但我

随机推荐

  • aaa计费请求_什么是AAA(身份验证,授权和计费)?

    aaa计费请求 AAA or Authentication Authorization and Accounting is a term used to describe 3 functions in IT Mainly AAA is us
  • 导航样式

    鼠标滑过 bottom 黄线从中间展开到两边
  • NLP: 0基础应用T5模型进行文本翻译代码实例~

    文章目录 前言 一 目标文本是什么 二 模型调用步骤 1 引入库 2 导入模型 本文使用 t5 base 3 使用分词器对目标文本进行分词 4 对刚刚生成的分词结果进行目标语言的生成工作 5 对生成的目标语言进行解码工作 就可得到目标语言的
  • 一文读懂Matter协议的前世今生和未来

    从事Zigbee行业的应该都知道今年Zigbee联盟已经改名为CSA联盟 并推出一个全新的 定位于解决IOT碎片化的统一协议 即Matter协议 Matter协议的由来 Matter协议的前身CHIP Connected Home Over
  • 从一个数组中随机取出若干个数

    随机取数 下面给出从一个数组随机取出若干数字组成新书组和从一个数组随机取出一个数字的方法 代码如下 从一个数组中随机取出若干个元素组成数组 param Array arr 原数组 param Number count 需要随机取得个数 co
  • 如何确保事务提交后才执行异步操作

    参考博客TransactionSynchronizationManager和TransactionSynchronizationAdapter 场景 业务流程背景 对于 法律法规 法规库 标签管理 列表中的某一条数据 操作完标注和解析按钮后
  • Angular离线API文档安装指南

    需要的材料 nginx 官方angularjs zip 完整包 步骤 1 先上www angular org 下载个完整的zip包 2 到nginx 网站下载 nginx 3 修改 nginx 1 6 2 conf nginx conf 文
  • 利用win10自带的工具测硬盘读写速度

    利用win10自带的硬盘测试工具测读写速度 一 win q 打开搜索框 输入 cmd 找到命令提示符 右击以管理员身份运行 二 在命令框里输入 winsat disk 是默认测试系统盘的速度 不出意外都是C盘 三 当我们要想测试其他盘的时候
  • MySQL学习笔记——MySQL数据类型(拉勾教育数据分析实战训练营学习笔记)

    MySQL学习笔记 MySQL数据类型 MySQL数据库中 每一条数据都有其数据类型 主要可以分为数值型 字符串型和日期时间型三大类 说明如下所示 数值类型 TINYINT 一个非常小的整数 占1字节 如果是有符号 范围是 128 127
  • MFC窗口销毁过程

    MFC窗口销毁过程 考虑单窗口情况 假设自己通过new创建了一个窗口对象pWnd 然后pWnd gt Create 则销毁窗口的调用次序 1 手工调用pWnd gt DestroyWindow 2 DestroyWin
  • Elasticsearch实战-磁盘IO被打满

    背景 事情是这样的 一天下午4点42分左右 业务反馈我开发的服务在测试环境出现问题 返回资源数据是0 查日志发现是ES访问超时 相当于数据库挂了 持续了20多分钟自己恢复 咨询了ES团队 最终得到下面的答复 当前集群现状 1 当前集群数据I
  • python爬取研究生招生网招生信息

    import requests from bs4 import BeautifulSoup from pandas core frame import DataFrame import re import time class Gradua
  • Nginx惊群问题

    Nginx惊群问题 1 简介 简单来说 多线程 多进程 linux下线程进程也没有多大区别 等待同一个socket事件 当这个事件发生时 这些线程 进程被同时唤醒 就是惊群 可以想见 效率很低下 许多进程被内核重新调度唤醒 同时去响应这一个
  • 07.JavaWeb-Vue+elementUI

    1 Vue 功能替代JavaScript和jQuery 基于JavaScript实现的前端框架 1 1配置Vue 1 1 1引入vue库 方法一 通过cdn链接引入最新版本的vue 可能会慢些 方法二 将vue库下载到本地 通过相对路径引入
  • SpringFramework核心技术三:Spring的验证机制

    Spring验证 Spring 3引入了对其验证支持的几项增强 首先 现在完全支持JSR 303 Bean验证API 其次 当以编程方式使用时 Spring的DataBinder现在可以验证对象并绑定到它们 第三 Spring MVC现在支
  • 【已解决】容器镜像安装vim的踩坑之路

    一 背景 在部署 Elasticsearch 7 17 7 版本时 进入到改容器后 发现该镜像没有vi 同时使用apt也无法正常安装 于是百度找解决方案 一步一坑 最后完美解决 二 解决 首先进入镜像中 docker exec it es
  • springboot+mysql物流车辆管理系统-计算机设计源码84722

    摘要 由于数据库和数据仓库技术的快速发展 物流车辆管理系统建设越来越向模块化 智能化 自我服务和管理科学化的方向发展 物流车辆管理系统对处理对象和服务对象 自身的系统结构 处理能力 都将适应技术发展的要求发生重大的变化 物流车辆管理系统除了
  • 基于深度学习的智慧城市火灾检测方法

    1 文章信息 本次介绍的文章是在2022年发表在Electronics的一篇文章 文章题目为 Fire Detection Method in Smart CityEnvironments Using a Deep Learning Bas
  • 工厂方法模式-Factory Method Pattern

    工厂方法模式 Factory Method Pattern 工厂方法模式 Factory Method Pattern 定义一个用于创建对象的接口 让子类决定将哪一个类实例化 工厂方法模式让一个类的实例化延迟到其子类 工厂方法模式又简称为工
  • 【爬虫】九、综合案例之m3u8文件

    视频网站常规处理方法 用户上传视频 gt 转码 处理视频 gt 切片处理 把单个文件进行拆分 一般把拆分好的文件放到M3U8 txt json的文本中 用户在拖动进度条时则进入到某个分片中 需要一个文件记录 1 视频播放顺序 2 视频存放路