讲师中心 微信公众号

工具推荐

视频效率加速
剧云
剧云

中文短剧剧本制作平台

立刻MV
立刻MV

低成本歌曲 MV、视频生成

Laper
Laper

剧本策划到成片协作

updream

一键生成高质量推广成片

Course Video Downloader

Polar Sponsor
爱发电 赞助
.NET 9.0

课程视频抓取与下载技能。通用型方案,适配任意课程平台。流程:用户提供课程链接→浏览器打开→检测登录墙(需要登录则弹窗让用户手动操作)→登录完成后分析页面→提取视频直链(video

课程视频抓取与下载技能

功能概述

课程视频抓取与下载技能是一项面向实际任务的技能,主要用于通用型课程视频下载方案,适配任意课程平台(腾讯课堂、B站、超星学习通、网易云课堂、学堂在线、小鹅通等);无法录屏 :浏览器自动化没有录屏能力,但通过抓取视频源文件直链下载,画质更好、速度更快;

核心要点

  • DRM 加密视频无法下载 :如果平台使用 blob URL、Widevine/DRM 加密流,只能建议用户用 OBS 手动录屏;
  • 不同平台适配程度不同 :需要根据页。
  • 它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。

使用与执行

从功能定位来看,该技能强调把分散的操作要求整理成清晰、可复用的处理流程,使用户能够围绕既定目标快速准备输入、选择执行方式并获得结构化结果。实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;

结果检查与注意事项

若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。

课程视频抓取与下载技能

通用型课程视频下载方案,适配任意课程平台(腾讯课堂、B站、超星学习通、网易云课堂、学堂在线、小鹅通等)。

核心限制

  • 无法录屏:浏览器自动化没有录屏能力,但通过抓取视频源文件直链下载,画质更好、速度更快
  • DRM 加密视频无法下载:如果平台使用 blob URL、Widevine/DRM 加密流,只能建议用户用 OBS 手动录屏
  • 不同平台适配程度不同:需要根据页面结构动态分析

工作流程

第一步:接收链接 & 打开页面

用户提供建议课程链接后,用 browser 导航打开:

import sys, os
sys.path.insert(0, os.path.join(os.getenv("SKILL_PATH"), "browser", "scripts"))
import browser

result = browser.navigate(url="用户提供的链接")
print(result)

第二步:检测登录墙

分析页面快照中的文本和交互元素,判断是否需要登录:

判断标准(命中任一即触发):

  • 页面文本包含"登录""注册""请先登录""登录后观看"等字样
  • 存在登录按钮、登录表单(用户名/密码输入框)
  • 视频区域显示"登录后即可观看"或类似提示
  • 页面跳转到了登录页

如果需要登录:

  1. 停止浏览器操作,告诉用户遇到了登录要求
  2. 调用 ask_user_question,提供选项:「弹出浏览器我自己操作」/「放弃」
  3. 用户选择接管后,调用 browser.request_manual() 弹窗
  4. 立刻再次调用 ask_user_question 询问用户是否完成操作
  5. 用户确认完成后,调用 browser.get_interactive_elements() 读取当前页面快照,继续后续流程

第三步:分析课程页面结构

登录成功后,分析页面结构:

  1. 课程目录/章节列表:找到课程章节、课时列表的元素索引
  2. 视频播放区域:定位 标签或 iframe 嵌入
  3. 章节展开:如果章节默认折叠,需要逐个点击展开

使用 browser.execute_script() 提取页面关键信息:

# 提取所有 video 标签的 src
result = browser.execute_script("""
    const videos = document.querySelectorAll('video');
    return Array.from(videos).map(v => ({
        src: v.src || v.currentSrc,
        sources: Array.from(v.querySelectorAll('source')).map(s => s.src)
    }));
""")
print(result)
# 提取所有 iframe(有些平台视频嵌在 iframe 中)
result = browser.execute_script("""
    const iframes = document.querySelectorAll('iframe');
    return Array.from(iframes).map(f => ({ src: f.src, id: f.id }));
""")
print(result)

第四步:提取视频直链

根据页面情况,采用不同策略提取视频地址:

策略 A:直接 video 标签

  • 如果 标签有直接的 src(mp4/webm/ogg),直接获取

策略 B:m3u8 流

  • 通过 Network 请求拦截或页面 JS 变量中查找 m3u8 地址
result = browser.execute_script("""
    // 尝试从全局变量和常见的播放器对象中提取
    const results = [];
    // 检查 window 上的视频相关变量
    for (const key of Object.keys(window)) {
        try {
            const val = String(window[key]);
            if (val.includes('.m3u8') || val.includes('.mp4')) {
                const match = val.match(/https?:\/\/[^"'\s]+\.(m3u8|mp4)[^"'\s]*/);
                if (match) results.push(match[0]);
            }
        } catch(e) {}
    }
    // 检查所有 script 标签中的视频地址
    document.querySelectorAll('script').forEach(s => {
        const matches = s.textContent.match(/https?:\/\/[^"'\s]+\.(m3u8|mp4)[^"'\s]*/g);
        if (matches) results.push(...matches);
    });
    return [...new Set(results)];
""")
print(result)

策略 C:XHR/Fetch 拦截

  • 注入网络请求拦截器,等待视频数据加载后捕获请求 URL
# 注入 fetch 拦截器
browser.execute_script("""
    window.__videoUrls = [];
    const origFetch = window.fetch;
    window.fetch = function(...args) {
        const url = typeof args[0] === 'string' ? args[0] : args[0]?.url || '';
        if (url.includes('.m3u8') || url.includes('.mp4') || url.includes('video')) {
            window.__videoUrls.push(url);
        }
        return origFetch.apply(this, args);
    };
    const origOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function(method, url) {
        if (url.includes('.m3u8') || url.includes('.mp4') || url.includes('video')) {
            window.__videoUrls.push(url);
        }
        return origOpen.apply(this, arguments);
    };
""")

策略 D:进入 iframe 内部提取

  • 如果视频嵌在 iframe 中,需要进入 iframe 的文档上下文提取

第五步:下载视频

获取到视频直链后,使用 Python 下载:

import requests
import os

def download_video(url, save_path, filename):
    """下载视频文件"""
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        'Referer': '当前课程页面URL',  # 部分平台需要正确的 Referer
    }
    
    # m3u8 需要 ffmpeg 下载
    if url.endswith('.m3u8'):
        download_m3u8(url, save_path, filename)
        return
    
    # mp4 直接下载
    resp = requests.get(url, headers=headers, stream=True)
    total = int(resp.headers.get('content-length', 0))
    downloaded = 0
    filepath = os.path.join(save_path, filename)
    
    with open(filepath, 'wb') as f:
        for chunk in resp.iter_content(chunk_size=8192):
            if chunk:
                f.write(chunk)
                downloaded += len(chunk)
                if total > 0:
                    progress = downloaded / total * 100
                    print(f"r下载进度: {progress:.1f}% ({downloaded}/{total})", end="")
    print(f"n下载完成: {filepath}")

m3u8 下载(需要 ffmpeg):

def download_m3u8(m3u8_url, save_path, filename):
    """使用 ffmpeg 下载 m3u8 视频流"""
    import subprocess
    filepath = os.path.join(save_path, filename)
    
    # 先检查 ffmpeg 是否可用
    try:
        subprocess.run(['ffmpeg', '-version'], capture_output=True, check=True)
    except FileNotFoundError:
        print("未安装 ffmpeg,正在尝试用 requests 直接合并 ts 片段...")
        download_m3u8_fallback(m3u8_url, save_path, filename)
        return
    
    cmd = [
        'ffmpeg', '-i', m3u8_url,
        '-c', 'copy', '-bsf:a', 'aac_adtstoasc',
        '-y', filepath
    ]
    subprocess.run(cmd, check=True)
    print(f"下载完成: {filepath}")

第六步:批量处理课程章节

如果课程有多个章节/课时:

  1. 先提取课程目录结构和所有章节链接
  2. 按顺序逐个进入章节页面
  3. 对每个页面执行视频提取和下载
  4. 下载完成后回到目录页,进入下一章节
  5. 记录已下载列表,支持断点续传
# 批量处理示例伪代码
chapters = extract_chapter_list()  # 从页面提取章节列表
downloaded = []  # 已下载记录

for i, chapter in enumerate(chapters):
    if chapter['title'] in downloaded:
        continue  # 跳过已下载的
    
    print(f"[{i+1}/{len(chapters)}] 正在处理: {chapter['title']}")
    
    # 进入章节页面
    browser.click(element_index=chapter['element_index'])
    
    # 等待视频加载
    import time
    time.sleep(3)
    
    # 提取视频链接
    video_url = extract_video_url()
    
    if video_url:
        download_video(video_url, save_dir, f"{chapter['title']}.mp4")
        downloaded.append(chapter['title'])
    else:
        print(f"  未找到视频链接,可能需要特殊处理")
    
    # 返回课程目录
    browser.navigate(back_to_course_url)

输出规范

  • 所有视频保存到工作区下的 output/course_videos/ 目录
  • 文件命名格式:{序号}_{章节标题}.mp4
  • 生成一份下载记录文件 download_log.txt,记录每个文件的下载状态
  • 如果某些视频因 DRM 或其他原因无法下载,在记录中标注原因

常见平台适配要点

平台 特点 注意事项
腾讯课堂 视频嵌在 iframe,m3u8 流 需要 cookie 鉴权,先登录再抓
B站 BV号直链,有 CDN 可用 bili-api 或直接抓取
超星学习通 iframe + object 嵌入 需要进入 iframe 上下文提取
网易云课堂 m3u8 加密流 可能有防盗链,需要正确 Referer
小鹅通 微信生态,m3u8 部分需要微信授权
学堂在线 HLS 流 需要 cookie

错误处理

  • blob URL:视频使用 blob URL 时无法直接下载,提示用户使用 OBS 录屏
  • DRM 加密:检测到 Widevine/PlayReady 等加密时,提示用户无法绕过
  • 防盗链:下载失败时尝试添加正确的 Referer 和 Cookie
  • 网络中断:支持断点续传(记录已下载进度)
  • 超时:单个视频下载超时 30 分钟则跳过,记录到日志

使用示例

用户只需说:

  • "帮我下载这个课程的视频:[链接]"
  • "抓取这个网课的视频"
  • "录制这个链接里的课程视频"

Agent 自动执行完整流程。

目录

热门AI工具

更多
Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

相关专题

更多
Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

0

2026.11.12

Go-Zero安装与goctl环境配置教程
Go-Zero安装与goctl环境配置教程

本专题围绕Go-Zero的安装与工具链配置展开,讲清Go版本要求、goctl安装方式、代理镜像、protoc依赖与环境变量设置,说明多版本共存、升级回退与CI流水线安装的做法,并整理安装阶段的常见报错与验证步骤。

0

2026.11.12

Go-Zero零基础入门教程
Go-Zero零基础入门教程

本专题整理Go-Zero的入门知识,从框架定位、环境准备到跑通第一个API服务,讲清目录分层、配置加载、日志与中间件的基本用法,并对比Gin、Kratos的差异,帮助Go开发者建立整体认知,判断它是否适合当前项目。

0

2026.11.12

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

0

2026.11.06

Postman请求头Headers怎么设置
Postman请求头Headers怎么设置

围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。

0

2026.11.06

Postman接口请求发送教程
Postman接口请求发送教程

详细介绍Postman接口请求的创建与发送方法,涵盖GET和POST请求、URL配置、请求参数、Headers请求头、Body请求体设置以及响应结果查看,帮助用户掌握Postman接口请求的完整操作流程。

0

2026.11.06

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

0

2026.11.05

DBeaver安全防护教程大全
DBeaver安全防护教程大全

DBeaver安全防护专题,围绕数据库连接安全、账号密码保护和访问权限管理展开,整理SSL/TLS加密连接、SSH隧道、数据库凭据保存及证书验证等配置方法,同时介绍敏感信息保护、远程连接风险和高权限账号使用等注意事项,帮助用户提高数据库日常管理的安全性。

0

2026.11.05

DBeaver连接创建与配置教程
DBeaver连接创建与配置教程

本专题聚焦DBeaver数据库连接配置与管理,覆盖从新建连接、选择数据库类型到填写连接参数和验证连接的完整流程。针对MySQL、PostgreSQL、SQL Server等常见数据库,整理相应的连接设置方法,并提供驱动缺失、认证失败和连接异常等问题的排查方向。

0

2026.11.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn