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 自动执行完整流程。

相关专题

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

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

2026.11.06

0

12

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

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

2026.11.06

0

13

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

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

2026.11.06

0

10

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

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

2026.11.05

0

12

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

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

2026.11.05

0

12

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

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

2026.11.04

0

16

XORM框架结构体映射与表结构同步
XORM框架结构体映射与表结构同步

本专题围绕XORM框架的结构体映射展开,说明表名与字段的命名策略、xorm标签常用属性、主键自增与时间字段自动填充,并演示Sync2自动建表、增量字段升级、索引声明与反向生成结构体的完整流程。

2026.11.04

0

15

XORM框架安装配置与数据库连接
XORM框架安装配置与数据库连接

本专题聚焦XORM框架的配置与连接环节,拆解MySQL、PostgreSQL、SQLite、SQL Server的DSN写法与驱动选择,讲清连接池参数、多数据源拆分、读写分离与超时重连的处理方式,并补充容器与兼容数据库的适配经验。

2026.11.04

0

15

XORM框架安装配置与数据库连接
XORM框架安装配置与数据库连接

本专题聚焦XORM框架的配置与连接环节,拆解MySQL、PostgreSQL、SQLite、SQL Server的DSN写法与驱动选择,讲清连接池参数、多数据源拆分、读写分离与超时重连的处理方式,并补充容器与兼容数据库的适配经验。

2026.11.04

0

16

热门下载

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

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 134.1万人学习