WorkBuddy 自动化实战:从零写一个带登录态和 Angular 操控的 Skill

4 阅读3分钟

以 OUCHN 教育平台自动化脚本为案例,完整走一遍:需求分析 → 架构设计 → 核心开发 → 踩坑修复 → 持续迭代。920 行 Python,日均处理 20 门课、120+ 次页面操作。


需求:辅导老师的日常三件事

国家开放大学辅导老师每天要在学习网上做三件事:

任务目标痛点
浏览课程资源100 页/天20+ 门课,逐一点击
批改学生作业不限分布在多门课,每份需评分+评语
回复论坛帖子10 条/天要找帖子、写回复

技术约束:需要短信验证码登录(无法全自动)、前端是 Angular 1.x(DOM 操作无效,必须走 scope)、Cookie 约 7-10 天过期。

架构:一个文件搞定

CONFIG           — 可调参数集中管理
Logger           — 日志类(文件+控制台双写)
Stats            — 统计类(计数+报告)
get_activities() — 获取活动列表(共享给子任务)
grade_course()   — 批改作业(Angular scope 操控)
browse_course()  — 浏览资源(多策略随机)
reply_forum()    — 论坛回复
main()           — 连接→登录→执行→报告

单文件 ~900 行。没有过度工程化——当功能规模在 1000 行以内时,文件拆分反而是负担。

核心技巧 1:活动列表共享

课程的活动列表只获取一次,三个子任务共享:

activities = await get_activities(page, course_id)
await browse_course(page, course_id, course_name, stats, activities)
await grade_course(page, course_id, course_name, stats, activities)
await reply_forum(page, course_id, course_name, stats, activities)

优化效果:浏览从 26 页 → 96 页 (+270%),批改从 30 份 → 62 份 (+107%)。每门课少掉了 2-3 次网络请求和 Angular 初始化等待。

核心技巧 2:Angular Scope 操作分步走

这是最复杂的部分。完整批改流程:

进入 full-screen 页面 → 等 10 秒(Angular 初始化慢)
→ 取 PagedSubmissionListController scope
→ 筛未评分学生
→ setViewingData(idx) 触发弹窗
→ 强制显示 modal(display:block)
→ 取 GiveScoreController scope
→ 设 score + comment,调 $apply()
→ 点"保存" → 隐藏 modal → 下一个

核心 JavaScript:

async (params) => {
    var psc = document.querySelector(
        "[ng-controller='PagedSubmissionListController']"
    );
    var s = angular.element(psc).scope();
    await s.setViewingData(params.idx);

    var m = document.getElementById('give-score');
    m.style.display = 'block';

    var g = angular.element(
        document.querySelector("[ng-controller='GiveScoreController']")
    ).scope();
    g.dataBindTo.score = params.score;
    g.dataBindTo.reviewer_comment = params.comment;
    g.$apply();

    var btns = document.querySelectorAll('#give-score button');
    btns.forEach(function(btn) {
        if (btn.textContent.indexOf('保存') >= 0) btn.click();
    });
    return 'ok';
}

关键细节:setViewingData() 是异步的必须 await、弹窗可能是 display:none 需要暴力设 block、$apply() 不调 Angular 不会知道数据变了。

四个真实踩坑

坑 1 — Select2 组件选不中角色:jQuery UI MultiSelect 组件直接设 DOM value 无效。必须走 Angular scope:scope.conditions.role = ['assistant_instructor']; scope.search()。修复后课程从 83 门降到 20 门。

坑 2 — Angular 初始化太慢:full-screen 页面等 3 秒后取 scope 返回 undefined。调到 10-15 秒才稳定。

坑 3 — Cookie 失效静默失败一周:6/16-6/22 期间脚本全失败,但没报错——Cookie 失效后被重定向到登录页,拿不到数据就退了。加了登录态检测逻辑后不再漏报。

坑 4 — 页面被关闭导致下一门课报 Target closed:加了 ensure_page() 恢复函数,检测到页面关闭自动新建。

持续迭代

版本改进效果
V1基本功能能浏览、能批改
V2Cookie 持久化不用每次登录
V3云端共享+多终端家里办公室都能用
V4角色筛选+活动共享性能提升 2-3 倍

每发现一个 bug,立即修到代码和 SKILL.md 里。 今天不修,下周就忘了上下文。


整套代码已在 WorkBuddy 上稳定运行,日均处理 20 门课、96 页浏览、62 份批改。关键不是代码多复杂,而是把坑都填平了。

📺 系列文章:第1节 Skill入门 | 第2节 CDP操控 | 第3节 云端部署