dsh-chaoxing
把大模型当司令,把脚本当手。
一个 DSH (DeepSeek Harness) Agent 预设:
工具里不含任何业务判断,让大模型在运行时自己适应一个千变万化的网站。
验证对象挑了个特别难的:学习通。
目录
为什么值得一看
自动化网页操作的传统做法是:把网站结构摸清楚,写成
if A 就做 X,else if B 就做 Y。
这条路只对结构稳定的网站有效。
本项目挑了一个反例来验证另一条路线。这个验证对象的特点是:
- 实测 6 门课 6 种页面结构,同一门课不同章节又各不相同
- 任务点类型不断冒出新的:视频 / 音频 / 测验 / 文档 / 专题 / 讨论帖 / 外链……
- 关键文字可能被字体混淆,从 DOM 里读出来是乱码
- 同一个「作业」模块,至少有 6 种以上形态
在这样的站点上,任何 if-else 都会在下一个没见过的页面上失效。
所以本项目走另一条路:
脚本只提供「眼睛」和「手」,所有判断交给大模型现场做。
这条路已经跑通:
| 实测结果 | |
|---|
| 章节测验 | 3 个真实测验,全部 100 分 |
| 视频 / 音频 | 原速播完,页面记账确认(verified: true) |
没见过的模块(pdf / 专题) | 大模型自己看、自己试,不需要改代码 |
| 能力边界 | 听力题 / 看视频题 → 自动识别并交还给人,不猜 |
它是什么
一个 DSH Agent 预设 + 14 个工具。装上之后,DSH 设置里会多出一个
「学习通模式」预设,切进去即可;禁用插件它就消失,不污染其他模式。
它在一个独立的浏览器里替代人工完成课程里的常规任务点
(看视频、做章节测验),并且只按真实学习的方式做:
- 原速 1x 播放,不倍速
- 不拖拽进度条
- 不伪造播放心跳
- 同一时间只做一件事
设计要点
一、工具要么报告事实,要么执行一个明确指令
每个 cx_* 工具都属于两类之一:
- 传感器:如实报告页面上有什么 —— 不加工、不结论、不隐藏
- 执行器:执行一个明确的动作 —— 不替你想该不该做
工具里不允许出现业务分支。 没有
「if 是视频就播放 else if 是测验就作答」这种东西。
二、不给任务类型写死逻辑,而是给通用的手和眼
除了高层工具,还有四个不含任何任务知识的通用件:
| 工具 | 作用 |
|---|
cx_dom | 眼睛:列出这一页所有可点的东西(含子窗口),每个一个编号 |
cx_click | 手:按编号 / 按文字 / 按坐标点击 |
cx_scroll | 手:往下翻 / 翻到底 |
cx_type | 手:往输入框写字 |
所以遇到从没见过的模块,大模型可以自己看、自己试、自己适应 ——
不用等作者加代码。
三、能力边界是一等公民
工具会明确说出「这件事我做不到」,而不是含糊失败或瞎猜。
比如页面同时有音频和测验时,工具会主动标出:
{ "kind": "quiz", "action": "human", "needsHearing": true,
"boundary": "这一页有音频 → 极可能是听力理解题。你没有听觉能力,不要猜答案。" }
四、上下文隔离
判题很吃 token:一张题目截图进上下文约 1500~2000 token,而且会一直留着。
所以支持开一个常驻的「判题员」子智能体:
主脑 cx_do({ key, action: "read" }) → 拿到截图路径(★ 自己不看图)
判题员 read_image 读图 → 判断 → 只回 JSON
主脑 cx_do({ key, action: "answer", answers }) 提交
图只在判题员的上下文里出现,主脑里只多 30 个 token 的答案。
一门课 20 道测验,能省下 3~4 万 token。
五、静默的错误比失败更危险
工具不会平静地报告假消息。两个真实设计:
- 站在非学习页时,
cx_page 会先报 pageKind,并明说
「这不是"这里没任务点",而是"页面类型不对"」
- 播放完成后回读页面自己的记账(
aria-label)确认任务点真的翻成已完成,
而不是把「播完了」当成「完成了」
设计约束
下面这些是故意的设计约束,不是技术限制。它们定义了这个项目与其他自动化工具的分界。
| 约束 | 原因 |
|---|
| 原速 1x,永不倍速 | 服务端能算出「进度增长 ÷ 真实时间增长」,倍速可检测 |
| 永不拖拽进度条 | 心跳里 isdrag 参数单独记账:0=正常播,1=你拖了 |
| 永不伪造心跳 | 播放器每 60 秒自己上报(带 MD5 签名)。我们什么都不做,让视频真的播 |
| 严格串行 | 同账号不能同时播两个视频,会互相顶、进度作废 |
| 不破解人机验证 | 检测到就停下叫人。这是「自动化操作」与「攻击人机验证」的分界线 |
| 人脸识别 / 抓拍 → 直接拒绝 | 唯一原理上无法诚实完成的机制 —— 它要求摄像头前坐着真人 |
| 不代填账号密码 | 只让你扫码。密码不经过本项目的任何一行代码 |
使用须知
- 本项目会自动操作学习通网页,该站的服务条款可能禁止或限制此类操作。
请自行确认你所在课程 / 学校 / 机构允许这样做。
- 使用者自行承担全部责任。 作者不对账号封禁、成绩作废或任何其他后果负责。
- 本项目不用于作弊:不破解验证码、不伪造播放心跳、不代替本人参加考试,
遇到需要真人在场的机制(人脸识别)主动拒绝执行。
快速开始
环境要求
- Windows / macOS / Linux
- Node.js ≥ 20(DSH 自带运行时即可)
- 一个 Edge 或 Chrome
安装
# 1) 把插件放到任意目录(下面用 D:\plugins\dsh-chaoxing 举例)
git clone https://github.com/LeuJasYoh/dsh-chaoxing.git D:\plugins\dsh-chaoxing
# 2) 运行安装脚本(会先备份 profile 的 package.json)
cd D:\plugins\dsh-chaoxing
pwsh -File .\install.ps1
# 先预览不写入:
# pwsh -File .\install.ps1 -DryRun
#
# 回滚:
# pwsh -File .\install.ps1 -Rollback "<备份文件路径>"
# 3) 重启 DeepSeek Harness
启用
- 重启 DSH
- 打开 **设置 → 「Agent 预设」**区块(不是顶部下拉框)
- 在**「自定义」**分组里找到 学习通模式
- 如果新任务选择器里看不到,去 通用设置 → 打开「代码工作工具」
使用
你 :切到「学习通模式」,帮我把 XX 课刷一下
DSH :cx_open → 浏览器打开课程站点
你 :用手机 App 扫码登录
DSH :cx_courses → 列出课程和进度 → 你选一门
DSH :cx_chapters → 找出还有剩余任务点的章节
DSH :(开始循环:进小节 → 看清整节 → 逐个任务点处理 → 下一节)
DSH :【收尾汇报】做了什么 + 需要你处理的清单
工具清单
看(传感器)
| 工具 | 作用 |
|---|
cx_open | 接管浏览器并打开站点,报告登录状态 |
cx_courses | 列出课程及权威进度(已完成任务点 X/Y) |
cx_chapters | 列出章节结构 + 每个小节剩余的任务点数 |
cx_enter | 进入某个小节,返回页面(tab)列表 |
cx_page | ★ 这一页有什么(all:true 可一次看清整节所有页面) |
cx_shot | 截图(支持 clip 只截一块,用于「题目看不清」) |
cx_progress | 本地进度 + 攒下来的待办清单 |
cx_dom | ★ 通用眼睛:这一页所有可点的东西 |
做(执行器)
| 工具 | 作用 |
|---|
cx_tab | 翻到这一节的某个页面 |
cx_nav | 翻小节(下一节 / 上一节) |
cx_do | ★ 对某一个任务点执行一个动作 |
cx_click | ★ 通用手:点击 |
cx_scroll | ★ 通用手:翻页 / 滚动 |
cx_type | ★ 通用手:写字 |
cx_do 的五个动作
| action | 用在什么上 | 说明 |
|---|
play | 视频 / 音频 | 原速播完并守护。播完回读页面记账确认(verified) |
read | 测验 | 等题目加载完,返回结构 + 截图路径 |
answer | 测验 | 作答并提交,先校对「浏览器里真的选中了这些」再提交 |
human | 听力题 / 看视频题 / 讨论帖 | 记入待办清单,然后继续(不打断) |
skip | 明确要跳过的 | 必须写理由,收尾时一并汇报 |
跨页编号 key
cx_page 返回的每个任务点都带一个 key,形如 "2:1"(第 2 页的第 1 个任务点)。
cx_do({ "key": "2:1", "action": "play" })
给 key 会自动切到那个页面再动手 —— 不用先 cx_tab 再 cx_do 两步走。
它是怎么工作的
┌─────────────────────────────────────────────────────────┐
│ 大模型(司令) │
│ 决定:进哪节 / 翻哪页 / 做什么 / 怎么做 / 不确定怎么办 │
└───────────────┬─────────────────────────────────────────┘
│ 14 个 cx_* 工具
▼
┌─────────────────────────────────────────────────────────┐
│ 插件(手和眼) │
│ │
│ index.js 注册预设 + 工具 + 主脑闸门 │
│ lib/observe.mjs 所有「读」—— 不许有业务判断 │
│ lib/act.mjs 所有「做」—— 不许有业务分支 │
│ lib/inventory.mjs 把「读」整理成「这一页有几个任务点」 │
│ lib/browser.mjs CDP 底座(零依赖) │
│ lib/state.mjs 工作区文件 + 待办清单 │
└───────────────┬─────────────────────────────────────────┘
│ CDP over WebSocket
▼
┌─────────────────────────────────────────────────────────┐
│ 独立浏览器(专用 profile,进程级静音) │
└─────────────────────────────────────────────────────────┘
零依赖
只用 Node 内置能力和 CDP over WebSocket。没有 npm 依赖。
文件放哪
<工作区>/.chaoxing/
├── progress.json 进度 + 攒下来的待办清单
└── shots/*.png 所有截图
浏览器配置(约 1 GB、含登录态)留在 ~/.dsh/chaoxing/browser-profile,
跨会话共用(不用每次重新扫码)。
主脑闸门
子智能体调用任何 cx_* 工具都会被直接拒绝(NOT_THE_COMMANDER)。
判定用结构而不是记 ID:
ctx.agents.isOwnedBy(agentId, other) // 这个 agent 是不是另一个 agent 的子体?
是子体 → 不是主脑 → 拒绝。 这样换会话也不会把主脑自己锁死。
为什么必须:该站点禁止同账号并行。两个 Agent 同时动同一个浏览器 →
切页互相打断、播放被打断、状态彻底错乱。
汇报节奏
⛔ 必须当场打断: 图形验证码 / 未登录 / 熔断额度 / 人脸抓拍
📝 记下来继续: 听力题、看视频题、讨论帖、搞不定的未知模块
🔇 其余时间: 闷头干,不闲聊、不请示
💬 收尾汇报: 一次性说清「做了什么 / 需要你处理什么」
一门课有几十上百个任务点。如果每个不会的都打断用户一次,
用户会被打断几十次 —— 能做完的活先做完,剩下的攒起来一起说。
实测踩过的坑
这些不是猜的,是真实调试出来的。完整版见 docs/学习通事实.md。
| 坑 | 真相 |
|---|
| 用 CSS 类判断任务点是否完成 | ❌ ans-job-icon-clear 跟「完成」毫无关系。权威标记是 aria-label。用错会双向出错:漏判已完成的、误判未完成的 |
| 以为「一个页面 = 一个任务点」 | ❌ 实测 Video 3 同时挂着视频 + 章节测验;Listening 同时挂音频 + 听力练习 |
| 切 tab 后直接读内容 | ❌ 会读到上一页的陈旧数据。判据必须是 #cardId 变成目标值 |
| 用「有没有验证码元素」判断 | ❌ 页面常驻一堆 display:none 的隐藏遮罩 → 误报「验证码弹了」 |
| 认为题干混淆、选项可读 | ❌ 混淆按页面类型触发:独立作业页连选项都乱码 |
| 播放完成 = 任务点完成 | ❌ 实测音频播到 97.6% 正常结束,任务点状态纹丝不动。必须回读页面记账 |
| 把播放器的断点续播当异常 | ❌ 站点会自己 seek 回上次位置(实测 12.7s → 1964s)。这是正常行为 |
| 播放器刚点开就判「卡住」 | ❌ 要几十秒才读出 duration。加载期不能做卡顿判定 |
| 只认首页域名算已登录 | ❌ 学习页在另一个子域 → 误判未登录,工具在门口就拦住 |
不传 --user-data-dir 启动浏览器 | ❌ 会把命令交给用户正在用的浏览器,抢窗口且永远绑不上调试端口 |
用 pnpm install 重装 file: 依赖 | ❌ 删掉旧副本后 pnpm 认为「已是最新」不重建 → 插件没装上却报成功 |
能力边界
工具会明确告诉你做不到什么,而不是含糊地失败:
| 事情 | 能不能 | 为什么 |
|---|
| 播放视频 / 音频 | ✅ | 纯机械动作 |
| 读题目文字 | ⚠️ 只能靠截图 | DOM 里的中文可能全是乱码 |
| 答普通章节测验 | ✅ | 读图 + 推理 |
| 答听力理解题 | ❌ | 没有听觉 → 记入待办,交给用户 |
| 看视频才能做的题 | ❌ | 看不了视频 → 记入待办,交给用户 |
| 图形验证码 | ❌ | 不破解 → 当场停下,请用户输入 |
| 人脸识别 / 抓拍 | ❌ | 原理上无法诚实完成 → 直接拒绝 |
常见问题
Q:需要提供账号密码吗?
A:不需要,也不接受。 只让你在浏览器里扫码,密码不经过本项目的任何代码。
Q:能同时刷两门课吗?
A:不能,也故意不支持。 该站点禁止同账号并行,会互相顶、进度作废。
插件有严格的串行闸门。
Q:截图和进度存在哪?
A:<工作区>/.chaoxing/ 里。只有浏览器配置留在家目录
(约 1 GB,且要跨会话共用登录态)。
Q:判题员子智能体是必须的吗?
A:不是。题目少的时候主脑自己顺手就做了。题目多的时候开一个能省大量 token。
Q:支持哪些操作系统?
A:Windows 已验证。macOS / Linux 应该可用(找 Edge 或 Chrome 的路径已内置),但未实测。
Q:换别的网站能用吗?
A:不能直接用。 工具里的「读」(lib/observe.mjs)和「做」(lib/act.mjs)
都是针对这个站点的具体结构写的。
但架构本身是通用的 —— 换站点要做的是替换这两个文件,而不是改架构。
已知限制
- macOS / Linux 未实测(找 Edge / Chrome 的路径已内置,Windows 已验证)
- 播放器形态只验证了两种:视频(videojs)与原生音频(
<audio>)。
若出现新形态,需要靠通用手眼现场适应
- 判题员只能串行复用:本插件是严格串行的,真正并行需要开多个判题员,
仅在「只刷测验」时有意义
- 测验的题干混淆按页面类型触发:独立作业页连选项都会乱码,
所以一律靠截图,DOM 文本不可采信
开发
git clone https://github.com/LeuJasYoh/dsh-chaoxing.git
cd dsh-chaoxing
node --check index.js
node --check lib/observe.mjs
目录约定:
lib/observe.mjs —— 只读,不允许出现业务判断
lib/act.mjs —— 只做,不允许出现业务分支
index.js —— 只做注册与转发
贡献时请保持这条分界。
一旦工具里出现业务分支,这个项目就失去了它存在的理由。
许可
MIT
致谢
本项目是 DSH (DeepSeek Harness) 的第三方插件,
与站点官方无关。
页面机制的全部结论来自实际调试观测,没有使用任何逆向工程工具,
也没有绕过任何访问控制 —— 过程与证据见 docs/学习通事实.md。