重庆理工大学课表查询 Skill — 问一句"今天有什么课",自动登录教务抓课表、算周次、查学分
基于 Python + Playwright(真实浏览器自动过 SSO / 瑞数 WAF)
查课表还要打开教务系统、输入学号密码、忍受验证码和 WAF 拦截?本 Skill 把登录 → 抓课表 → 算周次 → 回答全链路自动化,以后每天只需问一句"今天有什么课",少一步是一步。
- 针对重庆理工大学定制:正方教务 + UIS 统一身份认证 + 瑞数 WAF,一条链路全打通
- 对话即所得:装成 Skill 后直接问,Agent 自动算好今天第几周、有什么课、几点到几点
- 零配置查询:课表抓一次存本地,之后查询纯本地计算,不登录、不联网、零依赖
⚠️ 其他使用「正方教务系统 + 统一认证」的高校可参考fetch_schedule_browser.py的 SSO 流程自行适配。
-
🔐 自动登录抓课表 — Playwright 真实浏览器走 UIS 统一身份认证,自动处理瑞数 WAF、SSO 换票,一键抓取整学期课表
$ python fetch_schedule_browser.py --year 2026 --term 1 ① 登录统一身份认证 (学号 1251*****25)... ② 获取 SSO ticket,进入教务系统... ③ 抓取 2026 学年第1学期课表... ✅ 抓取成功: 示例同学 / 应用化学 / 15 门课 → schedule_2026_1.json -
📅 智能查询 — 自动算今天是第几周,回答"今天/明天/某周周X 有什么课",带学分统计
$ python today_classes.py --date 2026-09-18 --markdown 📚 2026-2027 学年第1学期 · 第3周 周五 (2026-09-18) 🏫 花溪校区 · 共 2 大节(2 小节) | 节次 | 课程 | 教室 | |---|---|---| | 1-2节 08:20-10:00 | 示例课程A | **1教0101** | | 5-6节 14:00-15:40 | 示例课程C | **3教0303** | 🎓 今日学分 6.5 / 学期总学分 18.75 (34.7%)单日为三列 markdown 表格(节次+时间段 / 课程 / 教室),教室粗体,紧凑。
-
🗓️ 整周网格视图 —
--week 3七列(周一~日)表格,每大节一行,格内课程 / **教室**,节次列带时间段$ python today_classes.py --week 3 --markdown 📅 2026-2027 学年第1学期 · 第3周课表 🏫 花溪校区 | 节次 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日 | |---|---|---|---|---|---|---|---| | 1-2节 08:20-10:00 | | 示例课程A / **1教0101** | 示例课程B / **2教0202** | | 示例课程D / **操场** | | | | 3-4节 10:20-12:00 | 示例课程E / **1教0102** | | | | | | | | 5-6节 14:00-15:40 | | | | | | | | | 7-8节 16:00-17:40 | | | | | | | | | 9-10节 | | | | | | | | 📊 本周共 11 大节(11 小节)单周为七列 markdown 表格(周一~周日),每大节一行,格内
课程 / **教室**,节次列带时间段,教室加粗。 -
✏️ 自定义课程(v1.2.0) — 在
custom_courses.json中添加自习、选修等,查询时自动合并到课表[{"title":"自习课","teacher":"无","weekday":3,"weeks":"2-16周","sessions":"7-8节","room":"图书馆301","credit":0}] -
🎯 大节计数(v1.2.0) — 大学两节连堂:1-2节→第1大节,…,提问"有几节课"回答大节数(附小节数)
-
📐 输出格式规范化(v1.2.2) — 单日/单周紧凑输出:每大节一行
课程名称 / **教室**,节次带时间段,教室加粗 -
📋 原样输出强制(v1.2.3) — Agent 必须直接展示脚本 stdout,禁止自行重排/转 markdown 表格/丢失教室加粗
-
📝 Markdown 输出模式(v1.2.4) —
--markdown输出规范的 markdown 表格(单日三列 / 单周七列、教室**加粗),Agent 原样粘贴即可在聊天中渲染成真表格 -
📊 紧凑表格布局(v1.2.5) — 单日/单周均改为紧凑 markdown 表格:每大节一行,格内
课程 / **教室**,节次列带时间段,不含教师;不再使用<br>(避免聊天界面转义成字面量) -
👥 多教师省略号(v1.2.0) —
--list中多位教师(如张老师,李老师)只显示第一个+…(日常单日/单周表格不含教师) -
🔄 单双周 + 多段周次 — 正确解析
15-19周(单)、10-16周(双)、4-6周,9-12周,14-18周 -
⏱️ 第一周不完整兼容 — 开学日在周中时按自然周对齐,第一周不足 7 天也正确
-
⏰ 时间段显示 — 时间列显示上课时间段(如
10:20-12:00),跨节取起止,不再只是时间点 -
🏫 双校区作息 — 花溪(8:20 起 11 节)与两江(8:30 起 10 节),首次使用自动选择
-
🛡️ 隐私安全 — 学号密码只存本机
config.json(已 .gitignore),不上传任何第三方 -
🧰 依赖自动处理 — 自带
check_deps.py,缺失依赖自动下载安装
- 早上出门前问一句"今天有什么课",几节课、几点到几点、哪个教室,一目了然
- 想知道"这学期都有哪些课 / 总共多少学分",一条命令列全
- 换学期后重抓一次课表,整学期不用再登教务
| 方式 | 说明 |
|---|---|
| zip 包(推荐) | cqut-timetable-skill-2.0.0.zip — 解压即用,含全部 12 个文件 |
| GitHub Releases | Releases 页 下载对应版本源码包 |
| Git 克隆 | git clone git@github.com:Lee-Hilex/cqut-timetable-skill.git |
本项目自带 check_deps.py,安装 Skill 或首次使用时会自动检查环境依赖,缺失的依赖自动下载安装:
# 检查环境(会明确提示缺什么)
python check_deps.py
# 自动下载安装缺失依赖(playwright + Chromium)
python check_deps.py --install| 功能 | 依赖 | 说明 |
|---|---|---|
查询课表 today_classes.py |
零依赖 | 纯 Python 标准库,装好即用 |
抓取课表 fetch_schedule_browser.py |
playwright + Chromium |
check_deps.py --install 自动 pip install playwright + playwright install chromium |
cp config.example.json config.json编辑 config.json,填入学号密码:
{
"sid": "你的学号",
"pwd": "你的教务密码",
"campus": "huaxi",
"semester_start": "2026-09-02",
"class_time": {
"huaxi": [
["08:20", "09:05"],
["09:15", "10:00"],
["10:20", "11:05"],
["11:15", "12:00"],
["14:00", "14:45"],
["14:55", "15:40"],
["16:00", "16:45"],
["16:55", "17:40"],
["19:00", "19:45"],
["19:55", "20:40"],
["20:50", "21:35"]
],
"liangjiang": [
["08:30", "09:15"],
["09:25", "10:10"],
["10:30", "11:15"],
["11:25", "12:10"],
["14:20", "15:05"],
["15:15", "16:00"],
["16:20", "17:05"],
["17:15", "18:00"],
["19:00", "19:45"],
["19:50", "20:35"]
]
}
}| 字段 | 说明 |
|---|---|
sid / pwd |
统一身份认证账号(与 uis.cqut.edu.cn 相同) |
campus |
校区: huaxi(花溪)或 liangjiang(两江),决定用哪套作息时间 |
semester_start |
开学日期(第一周第一天,可能是周中;建议手动填写,如 2026-09-02) |
class_time |
按校区分组的作息时间表(花溪 11 节 8:20 起 / 两江 10 节 8:30 起) |
🔒
config.json已加入.gitignore,学号密码不会进入版本库。💡 首次使用(或旧版单作息配置)时,
today_classes.py会自动提示选择校区并升级配置,无需手动编辑class_time。📅
semester_start建议手动填写(如2026-09-02,开学当天;第一周周一会自动对齐为当周周一)。留空时抓取脚本会尝试自动检测,但未开学时教务返回的周次可能不准,检测结果会提示你人工确认,查询时也可手动输入一次。
python fetch_schedule_browser.py --year 2026 --term 1
# --term 1 = 秋季学期, 2 = 春季学期成功后:
- 生成
schedule_2026_1.json(包含姓名/学号/课程/老师/教室/周次/星期/学分) - 若
config.json未填semester_start,脚本尝试自动检测开学日期:已开学时直接写入;未开学时提示人工确认(未开学时教务返回的周次可能不准),也可之后查询时手动输入
# 第3周全周课表(网格视图,v1.2.0 新增)
python today_classes.py --week 3
# 今天有什么课(默认单日卡片)
python today_classes.py
# 指定日期
python today_classes.py --date 2026-09-18
# 第15周周四
python today_classes.py --week 15 --day 4
# 列出全部课程(旧表格格式)
python today_classes.py --list
# Agent / 聊天场景: 输出 markdown 表格(教室加粗,直接原样展示)
python today_classes.py --week 3 --markdown
python today_classes.py --date 2026-09-18 --markdown💡 终端直接看用默认 ASCII 网格;Agent 回答用户时用
--markdown,得到规范的 markdown 表格(七列×五行、教室**加粗),聊天界面会渲染成对齐表格。
✏️ 自定义课程(v1.2.0): 参考
custom_courses.example.json创建custom_courses.json,查询时自动合并到课表。
将本目录复制到 Agent 的 skills 目录,或在 Reasonix 中执行:
/install-skill <本目录路径>
🤖 安装引导:Agent 安装本 Skill 后,首次使用前会运行
check_deps.py检查环境依赖,缺失的依赖会自动下载安装(见上方「环境检查」)。查询功能零依赖,可立即使用。
之后直接对话(Agent 运行 today_classes.py --markdown,原样展示脚本输出):
你: 今天有什么课?
Agent:
📚 2026-2027 学年第1学期 · 第3周 周五
🏫 花溪校区 · 共 2 大节(2 小节)
| 节次 | 课程 | 教室 |
|---|---|---|
| 1-2节 08:20-10:00 | 示例课程A | **1教0101** |
| 5-6节 14:00-15:40 | 示例课程C | **3教0303** |
🎓 今日学分 6.5 / 学期总学分 18.75 (34.7%)
问整周课表时,Agent 同样原样展示
--markdown输出的七列 markdown 表格(每大节一行,教室已用**加粗,渲染后为粗体)。
cqut-timetable-skill/
├── check_deps.py # 环境依赖检查脚本: 缺失自动下载安装
├── fetch_schedule_browser.py # 抓取脚本: UIS 登录 → SSO → 教务会话 → 课表接口 → 开学日期检测
├── today_classes.py # 查询工具: 大节映射 + 单双周解析 + 学分统计 + 单日三列/单周七列表格输出(零依赖)
├── config.example.json # 配置模板(学号/密码/校区/作息时间)
├── custom_courses.example.json # 自定义课程示例(自习/选修等,v1.2.0)
├── sample_schedule.json # 示例课表(脱敏,演示用)
├── SKILL.md # Skill 定义(供 Agent 加载)
├── CHANGELOG.md # 更新日志(从 v1.0.0 起)
└── .gitignore # 忽略真实 config.json / custom_courses.json / 真实课表(含个人信息)
重庆理工的教务访问链路(这也是很多高校的通用结构):
用户 → uis.cqut.edu.cn(统一认证/CAS)
→ ehall.cqut.edu.cn(办事大厅)
→ 调 getApplicationUrl 接口(应用 code: UIVx60)拿 oauth ticket
→ jwxt.cqut.edu.cn/sso/yhiotlogin?ticket=... (SSO 换票)
→ jwglxt/kbcx/xskbcx_cxXsKb.html?gnmkdm=N2151 (课表接口)
关键点:
- 教务系统直接 requests 登录会被 瑞数 WAF 拦截(返回 202/挑战页),必须用真实浏览器执行 JS
- UIS 登录后从 ehall cookie 取
ump_token_pc-officeHall,调getApplicationUrl(应用 codeUIVx60为教务系统在平台的固定 code,与个人收藏无关)即可拿到 oauth ticket,无需点击任何 UI - 用 ticket 访问
sso/yhiotlogin完成换票,教务会话即建立 - 课表接口 POST 需带
xnm(学年)、xqm(学期: 3=秋季, 12=春季)、kzlx=ck
- 本项目仅供学习与研究,请遵守学校网络使用规定,勿高频抓取
- 学号密码仅存于本机
config.json,脚本不向任何第三方发送凭据 - 教务系统接口变动可能导致脚本失效,欢迎提 issue