
简介一份面向教师及教学管理人员的雨课堂辅助脚本聚焦常规评估之外的临时教学需求用于提前查看试卷答案与成绩。压缩包内仅有一个脚本文件格式为JavaScript体积约3千字节轻量便携资源标签标注为C#语言适合具备编程基础的读者阅读重点参考脚本中网络请求构造、接口调用与数据解析等思路。脚本虽小却覆盖登录认证、试卷信息获取、答案提交以及成绩查询等核心环节并涉及数据格式处理和异常错误应对可作为理解在线教学平台接口交互流程的迷你范例。代码风格简洁紧凑关键步骤均有注释便于二次修改和功能扩展。目前已有四千八百三十六人学习下载既适合教师快速部署使用也适合开发者学习如何通过脚本模拟用户操作。需要特别提醒实际使用应遵守雨课堂平台规则保障考试公平与数据安全。1. 雨课堂查看答案脚本真正能查的是发布后的成绩与答案“雨课堂查看答案脚本”这个标题里“提前查看”四个字最吸引人也最容易让人踩坑。雨课堂的学生端成绩、试卷和答案都存在服务端接口后面老师没有点击发布之前同一组接口返回的 JSON 里根本没有答案字段更不存在提前拿到数据的通道。脚本能做的不是抢时间差而是按课程 ID 轮询“成绩是否已发布”“答案是否已发布”这两个状态一旦状态放开就把题目、个人作答、正确答案和得分拉下来整理成本地文件。它适合想批量查询多个测验结果的同学也适合要核对发布情况的助教和任课老师。2. 先定位雨课堂网页端接口用 curl 拿到成绩与答案的原始 JSON雨课堂网页版是典型的单页应用成绩列表、答题详情都通过 XHR 请求返回 JSON再由前端渲染成页面。直接分析 HTML 会浪费很多时间正确的做法是打开浏览器开发者工具观察实际发出的请求把接口地址、请求方法、参数和 Cookie 都摸清楚再转成脚本。抓包这一步并不神秘也不需要任何代理工具Chrome 自带的 Network 面板已经够用。2.1 用浏览器开发者工具找雨课堂的 XHR 请求打开雨课堂网页端并登录按 F12 进入开发者工具切到 Network 面板过滤条件选择 Fetch/XHR。然后进入课程的测验入口手动点击一次“刷新成绩”或切换到某场考试面板里会立刻出现一批新请求。逐个点开看 Response找到包含自己课程名、分数、题目信息的那个接口。请求名里通常带有exam、score、answer、detail这类关键词但不同版本可能混淆命名最终要以 Response 内容为准。有的脚本喜欢在 Console 里注入一段代码让你“一键查看答案”。我一般不建议这么干尤其是从陌生人那里拿到的代码它可能只是在偷 Cookie而不是在查接口。自己在 Network 面板里观察数据比任何一键脚本都可靠。2.2 把接口请求整理成 curl 命令作为脚本基座在 Network 面板里右键目标请求选择 Copy as cURL复制出来的命令很长因为里面带了完整的 Cookie 和追踪参数。先把它保存到文本文件里再精简成下面这种可读形式curl -s https://yuketang.example.com/v3/exam/student_course_exam_list \ -H user-agent: Mozilla/5.0 \ -H cookie: sessionid填写你实际抓到的值 \ --data-raw {course_id: 123456, page: 1, page_size: 20}解释一下参数-s让 curl 静默输出不打印请求进度-H指定请求头Cookie 要整串放进去不要拆开--data-raw按原样发送 POST body这里传的是 JSON 格式参数。course_id、page_size这些字段名以你抓到的实际请求为准不同课程类型可能有差异。拿到原始 JSON 后建议再装一个jq做格式化否则压缩成一行的大对象几乎没法读curl -s https://yuketang.example.com/v3/exam/student_course_exam_list \ -H cookie: sessionid填写你实际抓到的值 \ --data-raw {course_id: 123456, page: 1, page_size: 20} \ | jq .data.exam_list[] | {exam_id, name, publish_status}这段命令把考试列表过滤成exam_id、name、publish_status三个字段。先弄清publish_status的取值再写脚本判断逻辑避免对未发布的考试做无意义请求。2.3 判断“能不能查答案”的字段不是试卷本身接口返回的数据结构在雨课堂不同版本里会变化但字段含义基本一致。关键是不要把“考试发布”和“答案发布”混为一谈字段示例含义脚本该做什么publish_status考试是否已经发布未发布直接跳过score_release_status成绩是否对学生开放未开放不查详情answer_released答案是否公布为 false 不拉题目my_score当前账号的分数作为结果直接展示question_list题目和阅卷信息仅在答案开放时解析很多脚本跑不通是因为直接拿publish_status当答案状态结果详情接口返回空列表。老师可能先公布成绩再公布答案甚至只公布分数不公布答案。发布状态要分开判断脚本里只对已经开放的数据做请求这样既稳定也不会对老师端造成多余压力。3. Python 实现雨课堂查询脚本轮询发布状态并导出成绩与答案把接口摸清之后就可以写正式脚本了。这里我用 Python因为 Python 处理 JSON 和后续导出 Excel、Markdown 都比较顺手。你也可以用 Node 或 shell 实现但核心逻辑不变遍历课程、遍历考试、判断发布状态、按需拉详情。3.1 先建虚拟环境避免依赖污染系统直接在系统 Python 里装库其实也能跑但换台电脑、换个 Python 版本就可能在conda和requests之间打架。常见做法是给脚本建独立虚拟环境mkdir ykt-script cd ykt-script python -m venv venv source venv/bin/activate # Windows 使用 venv\Scripts\activate pip install requests python-dotenvrequests负责 HTTP 请求python-dotenv用来读取.env配置文件。为什么不直接用标准库 urllib因为requests对 JSON、Cookie、超时和错误状态的处理更省事脚本里要反复POST多个接口用它能少写很多样板代码。3.2 主脚本遍历课程、判断发布状态、导出结果创建ykt_query.py写入下面这段代码。它只做三件事先拉课程列表再拉每门课的考试列表最后按发布状态决定是否请求详情。import json import os import sys import time import requests from dotenv import load_dotenv load_dotenv() BASE_URL os.getenv(YKT_BASE_URL, https://yuketang.example.com) COOKIE os.getenv(YKT_COOKIE, ) HEADERS { user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, cookie: COOKIE, content-type: application/json, } def post_json(path: str, payload: dict) - dict: 向雨课堂接口发 POST 请求并统一处理公共返回结构。 resp requests.post( f{BASE_URL}{path}, headersHEADERS, datajson.dumps(payload), timeout10, ) if resp.status_code 401: raise SystemExit(Cookie 过期请重新登录后复制 YKT_COOKIE) resp.raise_for_status() body resp.json() if body.get(code) ! 0: raise RuntimeError(f接口返回错误: {body.get(msg)}) return body.get(data) or {} def get_course_list() - list: data post_json(/v3/course/student_courses, {page: 1, page_size: 20}) return data.get(course_list) or [] def get_exam_list(course_id: str) - list: data post_json(/v3/exam/student_course_exam_list, { course_id: course_id, page: 1, page_size: 50, }) return data.get(exam_list) or [] def export_exam(exam: dict) - None: name exam.get(name, 未命名考试) if not exam.get(score_release_status): print(f[{name}] 成绩未发布跳过详情请求) return detail post_json(/v3/exam/student_exam_detail, {exam_id: exam[exam_id]}) result { exam_id: exam[exam_id], name: name, my_score: detail.get(my_score), answer_released: detail.get(answer_released), questions: [], } # 只有答案开放才拉取 question_list否则保持空数组 if detail.get(answer_released): result[questions] detail.get(question_list) or [] print(json.dumps(result, ensure_asciiFalse, indent2)) if __name__ __main__: if not COOKIE: raise SystemExit(缺少 YKT_COOKIE请先在 .env 中配置) if sys.stdout and hasattr(sys.stdout, reconfigure): sys.stdout.reconfigure(encodingutf-8) for course in get_course_list(): print(f课程{course.get(name)}id{course.get(course_id)}) for exam in get_exam_list(course[course_id]): export_exam(exam) time.sleep(1)代码里几个关键点post_json把 401 提前拦下来直接提示 Cookie 过期而不是等到后面解析 JSON 时报 KeyErrorexport_exam里有两个判断score_release_status控制是否查详情answer_released控制是否解析题目time.sleep(1)是低频请求保护20 场考试也会占用一段时间但比高频连续请求被限流强得多。如果要做定时轮询建议把间隔放到 30 分钟以上而不是几秒刷一次。3.3 用 .env 管理 Cookie不写死在代码里脚本本身不包含任何账号信息。在ykt-script目录下创建.envYKT_BASE_URLhttps://yuketang.example.com YKT_COOKIEsessionid你从浏览器复制的完整cookie运行脚本python ykt_query.py参数说明环境变量必须说明YKT_COOKIE是登录后的完整 Cookie从 DevTools 复制YKT_BASE_URL否接口域名默认使用示例地址.env千万别放进 zip 里。Cookie 等价于登录态交给别人等于把账号交出去。分发脚本时只给.env.example里面写占位符。4. 雨课堂查询脚本运行报错排查cmdlet 不认命令、Cookie 失效与编码乱码脚本写好了接下来出场率最高的是 Windows 上的环境问题。这里把最容易卡住的几个报错按出现频率排个序方便直接对号入座。4.1 报“无法将‘python’项识别为 cmdlet”时先查 PATH打开 PowerShell 运行python ykt_query.py最常见的报错是无法将“python”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。npm、git、pip命令也会出现一模一样的提示原因基本都是可执行文件所在的目录不在 PATH 里。先确认解释器到底装在哪where.exe python如果提示找不到说明没装或者没勾选加入 PATH。如果装了只是当前终端没刷新可以在当前窗口手动追加$env:Path ;$env:LocalAppData\Programs\Python\Python312;$env:LocalAppData\Programs\Python\Python312\Scripts python --version注意这个修改只对当前窗口有效。要永久生效更安全的做法是打开系统环境变量面板在 Path 里新增两个目录而不是用setx直接覆盖因为setx可能把原有 Path 值冲掉。4.2 在 PowerShell 中遇到禁止运行脚本时用 RemoteSigned如果你是通过.ps1文件启动脚本还会遇到另一句高频提示因为在此系统上禁止运行脚本这是 PowerShell 执行策略在拦截。先看当前策略Get-ExecutionPolicy -List然后给当前用户设置 RemoteSignedSet-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -ForceRemoteSigned 的含义是本机创建的脚本可以运行从网络下载的未签名脚本会被拒绝。这个策略比Unrestricted稳妥适合开发机和个人电脑。如果你只是想让脚本定时自动跑也可以不碰.ps1直接在任务计划程序里加一个“登录时启动”的任务运行python ykt_query.py这样连终端窗口都不用手动开。在 Linux 或 macOS 上做定时轮询我更习惯用 shell 循环#!/usr/bin/env bash while true; do python ykt_query.py run.log 21 sleep 1800 done这段脚本每 30 分钟跑一次。21很关键它把标准错误也写进run.log否则接口 401 这类异常只出现在终端上日志文件里什么都看不到。4.3 Cookie 过期后接口返回 401处理比续期更重要雨课堂的登录态不是永久的Cookie 过期后接口大概率返回 401或者业务码code不为 0。很多人这时候会去找“保持登录”的取巧办法其实没必要。重新打开网页端登录一次从 Network 面板复制新 Cookie替换到.env里就行。脚本里已经处理了 401日志里看到“Cookie 过期”就直接去更新。如果以后想改提示把post_json里的SystemExit换成更具体的输出也可以。常见的几个错误现象和处理动作可以对照这张表现象最可能原因处理动作401 UnauthorizedYKT_COOKIE 过期重新登录并复制 Cookie404 或 400接口路径或参数调整重新抓包更新请求字段KeyError: exam_id接口没返回考试详情先判断发布状态再取字段中文乱码Windows 控制台默认 GBK用PYTHONIOENCODINGutf-8或脚本内 reconfigure4.4 中文乱码和 zip 解压后的乱码文件名在 Windows 控制台运行脚本时Python 默认输出可能撞上 GBK 编码报UnicodeEncodeError。脚本开头已经有sys.stdout.reconfigure(encodingutf-8)如果还不行就在 PowerShell 里设置$env:PYTHONIOENCODING utf-8至于解压.zip之后看到的乱码文件名问题和脚本本身无关多半是压缩包使用了非 UTF-8 编码打包。这种 zip 建议让对方用带 UTF-8 选项的打包命令重新处理或者用 7-Zip 手动打包。5. 雨课堂脚本 .zip 打包交付排除凭据、固定依赖与先验清单拿到一份“雨课堂查询脚本.zip”第一步不是解压后直接双击而是先看压缩包内部结构。交付别人脚本时也一样规范的 zip 应该包含一个带有版本信息的根目录避免解压后散落一桌面文件同时把.env、虚拟环境和缓存目录排除在外。推荐的目录结构是ykt-script/ ├── .env.example ├── README.md ├── requirements.txt └── ykt_query.py打包命令可以这样写cd ykt-script zip -r ykt-script.zip ykt-script \ -x ykt-script/.env \ -x ykt-script/__pycache__/* \ -x ykt-script/venv/*-x是排除规则。.env里是真实 Cookie不能给任何人venv是本地依赖目录又大又不通用__pycache__是 Python 运行时生成的缓存排除后不影响功能。这样打出来的 zip体积小也不会有泄露登录态的隐患。收件方拿到压缩包后先跑两条命令验证unzip -l ykt-script.zip sha256sum ykt-script.zipunzip -l列出当前目录所有文件检查里面有没有多余的.exe或隐藏文件确认requirements.txt存在sha256sum记录校验值防止传输过程中文件损坏。确认无误后再创建虚拟环境、按.env.example填自己的 Cookie 并运行脚本。这套流程跑通之后剩下要调的只是轮询间隔和导出格式不会再绕进环境问题里。本文还有配套的精品资源点击获取