培训网课视频自动挂机

SKILLAI 工具
AI 工具 未标注权限 许可证不明确
安装这个技能

网梯(WangTeng)培训平台网课视频自动挂机——自动续播+自动下一节+真实100%完成闸门+绝不跳过+自愈。适用 xnjj.nwafu.edu.cn 等北京网梯 learnspace 平台。触发词:挂网课、网课挂机、自动看视频、继续播、下一小节、培训平台网课

一句话选型结论

按资料字段整理

培训网课视频自动挂机是AI 工具类的 Agent Skill,安装方式未标注,权限级别未标注,许可证不明确,有可直接复制的安装命令。技能本质是给模型读的说明书,效果取决于模型与客户端;装完先用一个小任务验证,再放进正式流程。

分类AI 工具 安装方式未标注 权限级别未标注权限 许可证许可证不明确
累计安装 未标注 本周 未标注
GitHub 星标 未标注 仓库 未标注
下载量 未标注 技能市场下载数
权限级别 未标注权限 安装前请确认风险范围
许可证 许可证不明确 未说明

安装

未标注
在支持 Skills 的客户端里执行,装完问一句「你有哪些技能」验证
skillhub install user_c57ddd5f/wangti-course-autopilot
  1. 1
    确认客户端支持

    确认你的客户端支持 Skills(Claude、Codex、Cursor 等),并升级到较新的版本。

  2. 2
    拿到技能文件

    执行上面的命令安装;也可以把仓库里的 SKILL.md 手动放进客户端的 skills 目录。

  3. 3
    刷新技能列表

    重新打开客户端,或刷新技能列表,让新放进来的技能被加载。

  4. 4
    验证是否生效

    问一句「你有哪些技能」,确认列表里出现它,再拿一个小任务试跑。

技能档案

AI 工具
字段来自技能仓库与公开索引,中文说明由本站标注
作者 / 维护方user_c57ddd5f仓库 未标注 · 版本 未标注
宿主客户端未标注技能可被这些客户端加载
安装方式未标注安装包 community
权限级别未标注权限安装前请确认风险范围
许可证未说明许可证不明确,商用前请自行确认条款
仓库可用性available技能仓库当前是否可访问
最近核验未标注上游最后核验时间 · 数据更新 1791713500
正文体量27.9 KBSKILL.md 原文大小,越大说明说明书写得越细

典型使用场景

3 类
按分类整理的常见用法,具体以 SKILL.md 为准
组合多个 AI 能力

把写作、检索、总结串成一条流程。

搭工作流

把固定流程做成可重复调用的步骤。

做提示词与评测

整理提示词并对比输出效果。

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有标注权限级别,实际能做什么要装好后确认。
  • 许可证不明确,商用或二次分发前先到仓库确认条款。
  • 没有做站内核验,内容以作者仓库为准。
  • 技能只是说明书,实际效果取决于模型与客户端,装完先用小任务试一遍。

更适合

  • 需要在AI 工具场景里给模型补一套做法的人。
  • 愿意先读一遍 SKILL.md、确认它会让模型做什么的人。

不太适合

  • 对许可证要求很严、必须明确可商用的人。
  • 只想装完就自动变强、不打算看说明书的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
技能权限级别安装方式累计安装宿主客户端安装命令
培训网课视频自动挂机当前 未标注权限 未标注 未标注 未标注 有
执行计划 只读 GitHub 仓库 151.5 万 Codex、Claude、Cursor 有
Playwright MCP 测试 浏览器控制 ClawHub 市场 136.5 万 OpenClaw 有
完成前的验证 未标注权限 GitHub 仓库 131.9 万 Codex、Claude、Cursor 有
子 Agent 驱动开发 只读 GitHub 仓库 131.2 万 Codex、Claude、Cursor 有
前端设计 执行命令 GitHub 仓库 125.6 万 Codex、Claude、Cursor 有

SKILL.md 全文

27.9 KB
模型实际读到的说明书原文,来自技能仓库

网梯培训平台网课自动挂机

给"视频暂停自动续播、一节播完自动下一节"的完整可复现路径。以西北农林培训平台(xnjj.nwafu.edu.cn,北京网梯 learnspace)实测为准,同架构网梯平台通用。

前置

  • playwright-core:在脚本目录 npm i playwright-core 装一份,或用环境变量 NWAFU_PLAYWRIGHT_CORE 指向绝对路径(WorkBuddy 托管环境可直接指到其内置 playwright-core)。脚本优先读环境变量,否则 require('playwright-core')。
  • 系统浏览器:Edge C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe(agent-browser 自带 Chromium 下载必失败,别走那条路)
  • 登录凭据:姓名+手机号+图形验证码(验证码需人读,平台无账号密码登录)

第一步:浏览器常驻 + 填表 + 截验证码

浏览器必须常驻不关(验证码一次一变,截图和提交必须同一会话):

const { chromium } = require('...playwright-core');
const browser = await chromium.launch({
  executablePath: 'C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe',
  args: ['--no-sandbox', '--remote-debugging-port=9222'],
});
// goto 登录页 → await page.click('#loginTab2') 切到"学员登录"(⚠️LI无onclick,必须点A#loginTab2)
// fill('#user2', 姓名); fill('#pwd1', 手机号);
// await page.$('#captchaImg').then(e => e.screenshot({path:'captcha.png'}));
// 最后 await new Promise(()=>{}) 挂住进程不退出(run_in_background 跑)

人读验证码(Read 工具看截图),然后第二步:

const browser = await chromium.connectOverCDP('http://127.0.0.1:9222');
const page = browser.contexts()[0].pages()[0];
// ⚠️大坑:页面有两个 id="code"(注册面板隐藏的"输入手机验证码" + 登录面板可见的"输入验证码")
// 必须选可见的那个:
await page.evaluate(() => {
  const vis = Array.from(document.querySelectorAll('input')).find(i => i.id==='code' && i.offsetParent!==null);
  vis.value = '<验证码>'; vis.dispatchEvent(new Event('input', {bubbles:true}));
});
// 点登录:页面里 ^登\s*录$ 的可见元素(实测 A#sms-submit-btn2)

第二步:进课(⚠️不能直接拼课程URL)

直接访问 learnspace 课程 URL 会触发「长时间未操作…请重新登录」。正确路径:

  1. 登录后落到工作室 /ws/workspace/sso/workspace/student/index
  2. 点「网络课程」标签(changeToNetCoursesPage)
  3. 在课程列表页直接调页面自带函数:turnToLearn(courseId, classId)(从课程元素的 onclick 属性里抄这两个 ID)→ 新开课程页

第三步:摸清三层 iframe + 播放器结构

index.action (课程壳,含"学习时长:HH:MM:SS")
└─ courseware_index.action (章节/小节列表)
   └─ content_video.action (JWPlayer 播放器, <video> 在这里)
  • 小节节点:.s_point[itemtype=video],completestate=1=已完成,class s_pointerct=当前节(会滞后甚至永不刷新,绝对别信——2026-10-05 死循环事故根因:靠指针+1找下一节,指针不动就反复点同一节)
  • 精确当前节:解析 content_video 的 iframe URL params.itemId=<裸itemId>。
    ⚠️ 不同课程的小节元素 id 格式不一样:现代农业课 el.id 就是裸 itemId;肉羊肉牛课是 s_point_<itemId> 带前缀。匹配必须用后缀匹配:el.id === itemId || el.id.endsWith(itemId),点元素用 getElementById(pid) || getElementById('s_point_'+pid)
  • 换节:对 .s_point 元素 el.click() 合成点击即可(无需真实鼠标)
  • 新课第一次进:默认落在「课程简介」页,只有 course_detail.action 框架、没有播放器——必须在外层 index 框架点「课件」菜单(A#courseware_main_menu)才加载 courseware_index/content_video

第四步:挂机循环(5秒轮询)

1. 视频暂停且未播完 → video.play()(实测无需用户手势即可成功)
2. video.ended 或剩<1.5s → 点【document顺序第一个 completestate=0】的节点
   (按顺序学是平台强制的;若该节点恰是当前已加载的 itemId,说明完成状态没同步,等10s重查,等6次后强制点)
3. 全部 completestate=1 → 结束退出
4. 日志落盘(时间戳+当前节+进度+学习时长),便于随时 tail 对账
5. 页面弹 alert(如"请重新登录")→ page.on('dialog') 自动 accept 并记日志

自证指标

  • 学习时长每分钟 +1 分钟(页面壳的「学习时长:HH:MM:SS」)→ 平台真实计数
  • 小节播完后 completestate 自动翻成 1 → 完成标记有效

注意

  • 电脑不能休眠、浏览器进程不能杀(浏览器由启动脚本常驻持有)
  • 同一平台风控:短时间反复重登/异常操作会踢会话,正常顺序播放没问题
  • 验证码相关代码不含凭据;姓名/手机号别写进可分发的脚本里

v2 跨课程总管(2026-10-05 实战增量,直接抄 nwafu_supervisor.js)

单课挂机只解决一节课;要"一门听完自动跳下一门、一直听下去",用总管模式:

  1. 用 launchPersistentContext(userDataDir) 持久化 profile——cookie 落盘,重启进程不再要验证码(同平台会话期内)。注意返回值本身就是 context,没有 .contexts()。
  2. 课程进度存 JSON 状态文件(completedCourseIds),重启不重听已完课程;目标课=列表里第一个不在 completed 里的。
  3. 跨课程接力:本课全部小节 completestate=1 → 记入状态文件 → 关课程页 → 回工作室页调 turnToLearn 进下一门。判"全课完成"前先点章标题尝试展开折叠章节、重扫一遍,防漏判。
  4. 掉登录自愈:检测到 /login/ → 自动走登录流程;图形验证码用文件握手:截图存 captcha.png + 写 NEED 标记 → 轮询 captcha_answer.txt(由人/AI 读图后写入),120 秒没码自动点验证码图刷新重拍。
  5. 播完但 DOM 完成状态不翻(实测:这平台 completestate 是懒同步,DOM 短等 90s 也不会自己变)→ reload 课程页取服务器最新状态(reload 后可能落回“课程简介”,需再点「课件」菜单),重扫后该节即显示完成 → 自动进下一节。千万别重播当前节(白烧 15 分钟还永远不同步)。
  6. frames 加载超时自愈:30s 时诊断日志(打 URL+frame列表);90s 时先点「课件」菜单、再 reload;240s 放弃本尝试回列表重来。

v2.1 抗单节卡死 + 播放中自动写笔记(2026-10-05 增量)

v2 会把单节 sync 失败放大成整门课 STUCK 退出,实测「肉羊肉牛」S04 卡死导致后面 6 节全停。v2.1 改两点:

  1. 单节同步耐心 + 跳过机制:
    - 视频播完后等完成状态:30s → 90s。
    - 若 6 次 reload 仍显示 undone,不再 STUCK 整门课,改为跳过该节、点击下一个未完成小节继续播;跳过 ID 记进 state.skippedSectionIds(持久化在 nwafu_course_state.json),避免反复卡在同一节。
    - 代价:被跳过的该节学时可能不被平台计入,但保住了整门课其余进度和总学时。单节卡住就停整门,是更大损失。

  2. 播放中自动笔记写入:
    - 每进入一节课,在你的笔记目录生成/追加:<课程名>_笔记.md。
    - 每小节切换时记录:第N节标题、开始时间、视频时长、当前页面可见文字快照。
    - 每 5 分钟追加一次「画面文字快照」,抓取 courseware_index 框架(目录/课件文字)+ content_video 框架(字幕/文稿节点)的可见文字。
    - 笔记目录:自行指定一个本地目录(如你的笔记库下某目录),把路径配置成你的笔记文件即可;不配置则跳过笔记写入。

  3. 验证码 AI 自读:重启后若持久化 profile 掉登录,supervisor 会截图 nwafu_ctl/captcha.png 并轮询 nwafu_ctl/captcha_answer.txt。WB 可用 Read 工具直接读图片出数字,写入答案文件即可自动登录,无需人工手动。

v2.2 ASR 自动转写讲课逐字稿(2026-10-05 增量)

在 v2.1 基础上增加「小节播完自动抓音频 → faster-whisper 转写 → 追加进同一篇笔记」:

  1. 音频来源:复用浏览器登录态下载(不是 ffmpeg 直接下载)。
    - 播放开始后,清空并监听 context.on('response'),收集含 mp4/m3u8/ts/m4a/mp3 等后缀的媒体 URL。
    - 小节结束时,优先用 <video> 的 currentSrc,其次用监听到的最佳 URL。
    - 用 context.request.get(url, {timeout: 180000}) 下载媒体字节——它会复用同一 persistent context 的 cookie/登录态,绕过 CORS 限制;拿到后用 const buf = await res.body(); fs.writeFileSync(tmp, buf); 直接落盘,不通过 page.evaluate 序列化,所以支持大文件(默认上限 500MB)。
    - 下载失败、同域外资源、加密流或超上限时 fail-safe 跳过,绝不卡播放。

  2. 转写引擎:复用 stt 专用 venv(你自备的、已装 faster-whisper + imageio-ffmpeg 的 Python(用 NWAFU_PYTHON 指定解释器))。
    - Node supervisor 用 child_process.spawn 调用 transcribe_section.py <mediafile> <notepath> <section_label>。
    - Python 用 imageio-ffmpeg 的 ffmpeg 把媒体转 16k 单声道 wav,再用 faster-whisper small int8 中文识别。
    - 识别结果带 [MM:SS] 时间戳,追加到对应小节的逐字稿区块。

  3. 能力边界与真实率:
    - 能稳定产出逐字稿的前提是平台把音视频文件以「可直接下载的 mp4/m4a」形式下发,且同域或允许 CORS。
    - 很多 LMS 用 HLS/FLV/MSE 加密流,这种抓下来的只是分段/加密数据,ffmpeg 拼接复杂,成功率会显著下降。遇到失败会在日志里打 ASR: download failed ... 或 ASR: no media url ...。
    - 彻底兜底的方案仍是「虚拟声卡/ Stereo Mix 抓系统音频」——但这需要改默认播放设备或安装 VB-Audio,侵入性大,不作为默认。

  4. 依赖文件:与 nwafu_supervisor.js 同目录下需要 transcribe_section.py;脚本运行时自动创建 nwafu_tmp/ 临时目录。

v2.3 非阻塞 ASR + 退出等待(2026-10-05 修坑)

v2.2 把 child_process.spawn 用 Promise.race(..., 240000) 包起来并 await,结果:
- 一节 15 分钟音频在 CPU small/int8 下转写需要 5–15 分钟,240 秒必 TIMEOUT;
- TIMEOUT 后 JS 立刻 fs.unlinkSync(tmp) 删掉临时 mp4,正在跑的 Python 子进程读文件失败,逐字稿永远落不了地;
- await 还卡住小节切换,等于用播放进度换转写进度,双输。

v2.3 改两点:

  1. ASR 全程 fire-and-forget:小节结束时触发 captureAndTranscribe(...),但不 await。下载(20–60 秒)和转写(数分钟)都在后台跑,视频继续播下一节。日志会打印 ASR: section N transcription running in background。
  2. 子进程结束后再删临时文件:用 cp.on('close', ...) 在转写完成后记录 ASR: section N -> exit0 APPENDED len=... 并清理 tmp。进程退出前 await Promise.all(pendingASR),确保最后一节转写也完成才关闭浏览器。

因此,逐字稿不会立即出现在笔记里,而是每个小节播完后延迟 5–15 分钟异步追加;整门课完成后还需再等最后一节转写完。这是 CPU 转写的物理限制,不是卡住。

进程管理铁律(血泪)

  • 绝不在后台任务的命令里再套 &:node x.js & sleep 1 这种,TaskStop 只杀 shell 杀不掉 node 子进程 → 僵尸进程占着 profile,新进程 FATAL "Failed to launch browser"(exitCode=21),且日志新旧混杂极难排查。直接 run_in_background 跑 node x.js。
  • 重启前用 PowerShell 按 CommandLine 过滤杀干净旧 node + 对应 msedge(按 user-data-dir 匹配,别误杀用户自己的浏览器)。

v2.4 两处死锁修复(2026-10-05 晚间续做,已实跑验证)

v2.3 仍有两处会让 supervisor 整门课卡死或永不前进的死锁,本轮(课程2「聚焦未来农业」进不去,旧进程卡了 8 小时没动)实测踩中并修掉:

  1. 帧等待死循环(workOnCourse):旧逻辑 frameWait > 240 判定 frames 永不出现,但每次 page.reload() 都把 frameWait 归零 → 条件永远触发不了,卡在课程2 无限 reload 不前进。改:加 frameReloads 计数,连续 3 次 reload(每次 reload 后于 30s/90s 触发检测)仍无 courseware_index / content_video 两个 iframe → 返回 STUCK,交主循环跳过该课。
  2. STUCK/CRASHED 后只 sleep 60s 重试同一门、永不跳过:旧主循环遇到 STUCK 或 CRASHED 只 sleep(60000) 后重试同一门 → 卡一门永不前进。改:累计 failCount[cid],3 次后把该课写进 state.skippedCourseIds 并跳过,转向 targets 里下一门未完成课,保证 60 学时持续推进。
  • 两处均 node --check 通过;新 supervisor(PID 38944,2026-10-05 19:19 nohup 重启)实跑证明:按 skippedCourseIds 成功跳过课程2、转向课程3「酿酒葡萄栽培技术」正常播放 + 内置 ASR。
  • state.skippedCourseIds 初始化在主循环选课处;已 skip 的课程选课循环直接跳过(与 completedCourseIds 同逻辑)。

v2.5 崩溃残留自愈 + templateeight「课件」菜单点击修复(2026-10-06 修坑,已实跑验证)

v2.4 重启后 8 门被 skip 的课程仍播不了,本轮深挖日志发现是两类不同的根因叠加,分别修掉:

根因一:崩溃后页面目标损坏,单纯 reload() 治不好

  • 现象:「酿酒葡萄」11:19 能正常播 6 节;13:00 CRASHED 之后,再点任何课程,learnspace 页里只剩 index.action 一个 frame,course_detail.action 子 frame 完全不加载 → 点「课件」菜单失败 → 播放器 iframe 永远不出现 → STUCK ×3 → 写死 SKIP。
  • 误判:当时以为是网梯页面结构变了或这 8 门进不去,实际只是崩溃残留的损坏页面目标。
  • 修复:
    1. workOnCourse 检测 BROKEN-PAGE 特征:90s 时若 course_detail.action frame 仍缺失,直接返回 STUCK(不再傻等 3 次 reload)。
    2. 主循环遇到 STUCK/CRASHED 不再 sleep(60000) 重试同一页,而是关闭当前课程页 → 回 workspace 重新 turnToLearn 进入 → 新页面目标 healthy → 重跑 workOnCourse。最多 3 次真正失败才 SKIP。
    3. 清空 state.skippedCourseIds 里被误杀的 8 门(备份旧状态文件),让它们按新逻辑重试。

根因二:templateeight 模板要点「课件」里的 <a>,不能点 <li>

  • 现象:「聚焦未来农业」用 templateeight(其余课多为 templatethree),进了课程页后点 #courseware_main_menu(<li>)只高亮、不切换 iframe,course_detail.action 一直显示课程简介,永远出不来播放器。
  • 修复:菜单点击改点 <li> 里面的 <a> 链接;templatethree 里点 <a> 同样有效,兼容性不变。
    js const li = document.querySelector('#courseware_main_menu'); const m = li ? (li.querySelector('a') || li) : fallbackFindByText('课件'); if (m) m.click();

验证结果

  • 重启 supervisor(2026-10-06 08:11 左右,PID 5031),免 captcha 登录成功。
  • 肉羊肉牛(已 complete)快速判定完成。
  • 聚焦未来农业(之前 8 门里跳过的)在 30s 菜单点击后 5 秒内成功加载 courseware_index + content_video,PLAYING S01/6 稳定推进。
  • 说明 v2.5 的两处修复把那 8 门被误杀的课程重新救回,后续 60 学时可以继续累计。

已知内容缺口(不影响 60 学时)

  • 60 学时由平台按小节观看累计,与本地笔记 / ASR 解耦——supervisor 持续跑即稳步累计,ASR 逐字稿仅为内容复用增益,缺失不阻塞学时。
  • 肉羊肉牛课(已标记 complete)实测笔记里只有 S10 落了逐字稿;S08 因 v2.2 的 240s 超时坑虽下载但未转写(本轮后台补跑 transcribe_section.py 回填,完成后并入第8节下),S09 此前日志称成功但文件中缺失,S06/S07 早期 download/saveAs 失败无 wav。S06/S07/S09 需借浏览器登录态重抓 MP4 后转写,建议 supervisor 不忙时或单独 profile 跑,避免打断当前播放 + CPU 争用。
  • CPU 争用提示:一节课 15 分钟音频在 CPU small/int8 下转写 5–15 分钟;若 supervisor 内置 ASR 与手动补跑 ASR 同时跑,两个 whisper 进程抢核会各自慢到 30–50 分钟。补跑旧课 ASR 时尽量挑 supervisor 空闲档(小节切换间隙或课程间),否则耐心等。

v2.6 铁律:每门每节必须读完,绝不遗漏(运营方硬约束)

  • 根因(v2.5 之前):workOnCourse 里某节播放完但平台 completestate 未即时同步时,旧代码累计 6 次 reload 失败后把该节写进 skippedSectionIds 并跳到下一节,甚至"其余全跳过就当整门完成"——直接导致漏节。
  • 修复(v2.6):
    1. 删除所有单节跳过逻辑。一节只有平台 completestate==='1' 才算数;整门只有全部小节 completestate==='1'(含章节展开复查)才 COURSE_DONE。
    2. 一节播完未同步 → 重看同一节(secRetry 计数,reload + 重点同一 s_point 从头看),最多 15 次。
    3. 15 次仍不同步 → 不跳过、写 nwafu_ctl/section_stuck_<course>_<section>.txt 卡点标记 + 笔记告警,返回 SECTION_STUCK 退回主循环。
    4. 主循环遇 SECTION_STUCK:不标记完成、不写 skippedCourseIds,给该课挂 20 分钟冷却(cooldownUntil)后延迟整门重试;冷却期内其他课正常推进,避免饿死。该课因未 completed 会在后续循环被再次拾起,直到全部小节真正读完。
  • 验证:重启后 肉羊肉牛 重新拾取→平台 11 节全 done→立即 COURSE_DONE;聚焦未来农业 从已读 2 节处续播 S03,逐节推进,全程无 SKIPPING/SECTION_STUCK 日志。
  • 状态文件:nwafu_course_state.json 清掉手滑 junk id,仅留 2 门真实 completed + 空 skipped。

v2.7 互踢事故 + 进程栈五连修(实战,全部实测定位)

用户手动登录平台 → 同账号单端互踢 → supervisor 死亡。重启过程连环踩坑,修出五条铁律:

  1. 日志时间是 UTC:supervisor 的 log() 用 UTC(+8=北京时间)。诊断停摆时长时先换算,否则会把"停 1 小时"误判成"停 8 小时"。
  2. Git Bash 的 tasklist //FI 过滤不可靠:node 明明存在却返回空。查进程一律用 PowerShell Get-CimInstance Win32_Process(按 name + CommandLine 过滤),别信 tasklist。
  3. Edge exitCode=21 = profile 被占或损坏:一个 profile 目录被任何实例碰坏后,后续所有 launch 永远失败(换 args/删 Default/Lock 都没用)。修法:launch 包重试循环(6 次×6s),失败先清 SingletonLock/SingletonCookie/SingletonSocket/Default/Lock,3 次失败后直接换全新 profile 目录(cookie 丢了就走登录流程,验证码文件握手补上)。已在 supervisor 实装并实测生效。
  4. supervisor 必须寄居在唯一 guard bash 里:直接 run_in_background 跑 node 会被任务生命周期管理收割(数分钟后静默死亡)。但 guard 自身也会残留——本轮清出 11 个 guard bash + 4 个 supervisor node 互踩(每个 guard 拉自己的 supervisor 抢同一 profile)。重启标准流程:PowerShell 全杀(bash.exe 含 nwafu_guard + node.exe 含 nwafu_supervisor + msedge.exe 含 nwafu_profile)→ 确认归零 → 起唯一 guard。
  5. 验证码等待期禁刷新太早:doLogin 等码循环里 40s(i===8)自动点验证码图刷新,人读图+写答案要 30–60s,答案写进去时码已作废 → 连续"提交失败仍在登录页"。改成 i===36(180s)后一次登录成功。人读码务必在截图后尽快写入 captcha_answer.txt。

给用户的硬规矩:同账号两端在线必互踢。要手动登录看平台,先停挂机;看完退出,再恢复挂机。

v2.8 假活判别 + guard 停后残留 + FATAL_LOGIN 误判(2026-10-10 实战)

  1. 判活看业务指标,不看进程。guard 因 FATAL_LOGIN STOP 后,残留的 supervisor 可能还活着——卡在 frame.evaluate: Target page, context or browser has been closed + frames not ready 报错循环:进程在、Edge 进程在,但日志时间戳停止更新、零课时推进。判据:日志最后一行距今超过 2 个轮询周期 = 假活,杀干净重启,别被"进程还在"骗。
  2. 两份日志时区不同:supervisor 日志 = UTC;nwafu_guard.log 的 date '+%F %T' = 本地时(北京)。跨文件对时间线先统一 +8,否则把"停 1 小时"看成"停 9 小时"。
  3. FATAL_LOGIN(exit 2) 不一定是真掉登录:浏览器崩溃导致登录重试失败同样 exit 2。实测:guard STOP 后重启 supervisor,旧 profile cookie 直接登录成功、根本没弹验证码。先低成本重启试一次,再动用人工验证码。
  4. 全链路恢复 SOP(已验证):PowerShell 杀 nwafu_supervisor node + nwafu_profile msedge → 起唯一 guard(run_in_background)→ 轮询 nwafu_ctl/captcha_need.txt(不出现 = cookie 仍有效,无需人工)→ 看 guard task stdout 里 PLAYING 行的秒数在涨 = 真活。

v2.9 真实 100% 闸门 + 四连修(v4 重构,已实跑验证)

v4 把"完成"的定义从「DOM 标记」彻底换成「平台服务端统计」,并修了 3 个会让系统假完成/假死的坑。这是运营方「每门必须 100% 才算学时、零跳过」硬约束的工程落地。

① 真实 100% 闸门:只用平台「课程成绩」的 A/B(彻底弃用 completestate)

  • 平台权威信号:点 课程成绩 tab,读文本 学习资源 课程完成进度 A/B;活动资源 课程完成进度 C/D。这是服务端统计,必修课。
  • 放行判据:A===B 且 B>0 且 活动资源无缺口 才 COURSE_DONE 写 completedCourseIds。
  • DOM 的 completestate==='1' 只是"已访问"标记,不可信:实测肉羊肉牛 11 节 DOM 全 1,但服务端只 10/11;v3 据此误判完成、漏算 1 节学时。v4 一律以 A/B 为准。
  • 读取函数 readCompletion():先点外层 课程成绩,再进 iframe 内补点;点完直接读原 frame 对象(见 ③),失败回退 findFrame(),再回退外层 page.evaluate;都读不到打 COMPLETION_RAW + MENU_DUMP 诊断、记 unreadable 不崩。

② 重看必须「顺序遍历」,原 curIdx=0 是致命 bug

  • 坑:DOM 全标记完成但平台 A<B 时,旧逻辑 undone.length===0 分支每轮 curIdx=0 —— 永远只重看第 1 节,永远补不到服务端漏计的那节(尤其漏的若是 S02+),整门卡死在 10/11 之类,永不 COURSE_DONE。
  • 修:引入 rewatchMode(DOM 全完成但平台未完成),用 rewatchIdx 顺序遍历 S01→Sn,每节播完 rewatchIdx++;跑满 MAX_PASSES=4 轮仍 A<B → 写 needs_manual_&lt;course&gt;.txt + NEEDS_MANUAL 返回,主循环给该课挂 6h 长冷却、转下一门(不标记完成、不写 skipped、不跳过——冷却后会被再次拾起)。
  • 意外验证:肉羊肉牛漏的恰是反复 stall 的 S01,旧代码反复重播 S01 反而补齐,v4 闸门读到 11/11 才放行——双保险证明 A/B 闸门可靠。酿酒葡萄(10/11) 现正走 round 1 顺序重看补齐。
  • 已知代价:若漏的不是 S01,round 1 要顺序播到那节才会补上;最坏 4×11×~15min。比"永远卡死/假完成"划算得多。

③ templateeight 读取「三连修」(聚焦未来农业 这类课专用)

templateeight 模板和 templatethree 在 tab/iframe 行为上不同,旧代码在这类课直接 Cannot read properties of null (reading &#x27;a&#x27;) 崩溃循环:

  1. clickTab 真实点击兜底:DOM el.click() 后补 page.locator(&#x27;text=&quot;&#x27;+label+&#x27;&quot;&#x27;).first().click({timeout:4000,force:true}) —— 因为 templateeight 的 tab 是 addEventListener 绑定、无 onclick,JS el.click() 不触发。
  2. 点击后直读原 frame 对象:真实点击会让 iframe 原地导航到成绩页 URL(不再匹配 courseware_index),重 findFrame() 落空。修复:点击后直接读点击前的 frame 对象(Frame 对象跨导航依然有效),再回退 findFrame()/外层页。
  3. 读不到也不崩 + 诊断:comp.res 为 null 时日志打 unreadable(不 comp.res.a 抛 TypeError);并打 MENU_DUMP[outer/iframe] 列出 tab 文本与跳转目标,便于下次定位。

④ 双实例抢同一账号:按进程树精确清理,绝不用沙箱 tasklist

  • 现象:上一会话的 supervisor 成孤儿(其 guard bash 已死、pid 文件被清)仍活着,与新实例同时开浏览器互踢会话,两边都登录不了。
  • 查法(铁律):绝不用沙箱里的 tasklist(返回空,会误判"系统没跑")。一律 PowerShell Get-CimInstance Win32_Process(需 dangerouslyDisableSandbox)按 父进程链 + 启动时间 + 命令行 精确识别:本会话节点链是 WorkBuddy.exe → bash(guard) → node(supervisor) → msedge;插件运行时节点(如 25900/41224/54808)不动。
  • 杀法:先按命令行杀旧 guard bash 与旧 supervisor node,再 taskkill /PID &lt;old_node&gt; /T /F 连根清掉它拉起的 Edge 树;最后杀自己的旧 node 让 guard 以新代码重启。WorkBuddy 插件运行时进程严禁碰。

⑤ 验证码自解 + PROFILE 固定为已登录会话,重启全免验证码

  • 自解:supervisor 等码时截图 nwafu_ctl/captcha.png 并轮询 nwafu_ctl/captcha_answer.txt。WB 用 Read 工具直接读图出数字(如 3837)写入答案文件即可自动登录,无需人工手动(一次过 LOGIN SUCCESS)。
  • 根治:把 PROFILE 常量指向一个已带登录 cookie 的 persistent context 目录(如 nwafu_profile),重启直接读 cookie 秒登。实测 3 次重启全部免验证码——这是比"每次自解"更稳的一招。
  • 注意:PROFILE 被任何实例碰坏(exitCode=21)后,v2.7 的"换全新 profile 目录走登录流程"仍保留为兜底。

v4 整体架构(新人接手直接看这段)

  • nwafu_guard.sh:守护。循环拉起 supervisor;exit≠0 重试(login stuck 等 120s,其他 15s),exit 0 才 STOP。后台 task 常驻。
  • nwafu_supervisor.js(v4):真实 100% 闸门 + 重看顺序遍历 + templateeight 三连修 + 单实例锁(写 pid + process.kill(pid,0) 活性探测,stale 自动回收,重复实例 exit(3))+ 会话复用已登录 PROFILE + NEEDS_MANUAL 长冷却。
  • 状态文件 nwafu_course_state.json:completedCourseIds(真实 100% 才进)、skippedCourseIds(v2.6 起恒空——零跳过)、needsManual(恒空)。这两个空数组本身就是验收指标:零跳过、零卡死遗留。
  • 复盘文档:nwafu_v4_复盘与自愈机制.md(含完成状态表 / 8 踩坑 / 7 自愈机制 / 6 预判对策 / 验收口径),与本文档互为补充。

当前进度(实跑验证)

  • 已真实 100% 完成多门课程(均经平台「课程成绩」A/B 确认 100%),涵盖 5~11 小节的不同课型;DOM 全标记完成但平台未达 100% 的课会自动进入「顺序重看补齐」机制。
  • 其余课程按课程列表顺序接力,逐门冲 100%。
  • skippedCourseIds=[]、needsManual=[] —— 全程零跳过、零卡死遗留。

常见问题

5 问
答案由本站依据条目字段整理
培训网课视频自动挂机怎么安装?

在支持 Skills 的客户端里执行:skillhub install user_c57ddd5f/wangti-course-autopilot。安装方式为未标注。装完刷新技能列表或重开客户端。

培训网课视频自动挂机支持哪些客户端?

资料没有标注宿主客户端,但只要客户端支持 Skills(Claude、Codex、Cursor 等),一般都能加载。

培训网课视频自动挂机权限高吗,安全吗?

权限级别为未标注权限。安装前先看它会读取或写入哪些内容。

培训网课视频自动挂机收费吗?

本站不代收费用,也没有标注具体价格。是否收费取决于技能本身和所用的模型或客户端,正式使用前按作者说明确认。

培训网课视频自动挂机用什么许可证?

许可证标注为 未说明(许可证不明确)。商用或二次分发前请到仓库确认条款原文。

热门专题

按场景挑技能
全部专题 →

技能内容以作者仓库为准;分类、权限级别与许可证状态的中文说明为中文整理,最近核验 未标注。