Overview
补退选课程名额监控工具。它在本机 Chrome 中登录选课系统,按设定间隔读取补退选列表;当符合条件的课程出现空余时,发一封邮件提醒。
它只做查询和提醒,不会替你选课,也不会处理验证码。
请只用于自己的账号,并遵守学校的相关规定。登录、查询和翻页之间会保留随机间隔;遇到风控提示或验证码时,程序会停止本轮,而不是继续尝试。
Disclaimer
本工具仅用于个人课程选课状态的查询与提醒,不保证其正确性、稳定性或可用性。使用者应自行承担使用本工具带来的一切风险与后果;作者对因使用 courser 导致的任何直接或间接后果概不负责。
请合理设置并适当放大操作间隔(如 interval_min、page_delay_min/max 等),保持接近正常人类的操作节奏;不要用本工具进行任何批量、高频或违反规定的操作。
# 从 PyPI 安装(只带 rich/textual;opencli/gws 需另装,见下方)
pipx install courser # 推荐:独立 CLI 环境,不污染系统 Python
# 或装入当前 Python 环境:
pip install courser
# 更新
pipx upgrade courser # 推荐(pipx 安装时用这个)
pip install --upgrade courser # 或:pip install -U courser
uv tool upgrade courser # 若当初用 uv tool install
发布到 PyPI 只包含 courser 自身与
rich/textual两个 Python 依赖。 opencli / gws 不随包发布,需在本机单独安装(见下方 Quick start 的说明)。
Quick start
需要:Python 3.12+、uv、Chrome,以及两个已完成配置的命令行工具:
- OpenCLI:连接本机 Chrome。安装扩展、启动 daemon 后,运行
opencli doctor,确认检查通过。 - Google Workspace CLI(
gws):发送提醒邮件。 安装:npm install -g @googleworkspace/cli。 首次先执行gws auth setup(一次性初始化 Google Cloud 项目 / OAuth 配置 / 启用 API), 再执行gws auth login授权 Gmail;之后 token 失效时重新gws auth login即可。
git clone https://github.com/xjsongphy/courser
cd courser
uv sync
uv run courser
第一次启动会打开设置向导:填写收件邮箱保存后会自动生成 config.json(无需手动复制),其余设置可在程序的设置页完成。
若你更愿意由 Chrome 或密码管理器填充学号和密码,保持 credentials 为空即可;也可以写入 config.json,或通过环境变量 PKU_USERNAME、PKU_PASSWORD 提供。
What it does
- 每轮从 IAAA 登录,打开补退选页面,并按网站实际页数读取课程;不依赖固定页数。
- 按课程名、课程类别和开课院系筛选。可选择任一条件命中或全部条件命中。
- 只有“限数大于已选”的课程才会提醒;同一门课有冷却时间,邮件也有每小时上限。
- 提供一个终端界面查看最近结果、调整筛选和设置、查看日志。文字选择风格为 Textual 自接管:鼠标拖动选择、松手即自动复制到剪贴板(OSC 52),并 toast 提示;滚轮滚 页面,帮助 / 日志 / 详情页均可用。
Run one check
uv run courser --once
这会跑完一轮并把结果打印到终端,适合确认登录和筛选是否正常。持续运行则直接执行 uv run courser。
Configuration
config.json 会在首次启动向导完成时自动生成,一般情况下无需手动修改——轮询节奏、筛选条件、收件邮箱等都可直接在 TUI 的设置页修改并自动保存。以下为完整的配置结构说明(参考):
{
"interval_min": 8.0, // 查询间隔(分钟)
"interval_jitter": 0.3, // 间隔随机抖动
"page_delay_min": 0.8, // 翻页最小等待(秒,人类节奏)
"page_delay_max": 2.0, // 翻页最大等待(秒)
"session": "courser-watch", // opencli 浏览器会话名
"window": "background", // 浏览器窗口模式
"force_relogin": true, // 每轮是否强制重新登录
"credentials": { // 可留空(依赖浏览器密码管理器自动填充)
"username": "",
"password": ""
},
"filters": {
"names": [], // 课程名,子串匹配
"categories": [], // 课程类别
"depts": ["英语语言文学系"],
"match": "any" // any:任一条件命中;all:全部条件命中
},
"notify": {
"to": "you@example.com", // 收件邮箱(必填)
"gws_from": "", // gws 发件账号(可选,默认取认证账号)
"min_interval_min": 15.0, // 同一门课的通知冷却(分钟)
"max_per_hour": 5 // 每小时发送上限
}
}
config.json 不会提交到 Git。运行日志写入 data/courser.log。
Troubleshooting
opencli doctor 需要全部通过。若登录页填入账号密码后仍未跳转,先在同一个 Chrome 中手动完成一次登录,再执行 uv run courser --once。验证码和二次验证需要你本人处理,courser 不会代填。
Development
uv run python tests/unit/test_opencli.py
uv run python tests/integration/test_round_runner.py
uv run python tests/tui/test_navigation.py
uv run python tests/tui/test_responsive.py
真实网站的端到端检查仍需手动执行:
uv run courser --once
License
Metadata
Release files for courser 0.1.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| courser-0.1.6.tar.gz | 132.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| courser-0.1.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 232.4 kB
Release files / courser-0.1.6.tar.gz
| Download URL | courser-0.1.6.tar.gz |
|---|---|
| Size | 132.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b3fba2570874054a3b3d8d501961a6c7e8147ece4473262d10c5445475310cbf
|
|
BLAKE2b-256 checksum How to use checksums |
0c5da855266548c5dc02c9b87eebd0be0744798eb8d282b11529ec168156d345
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|
Release files / courser-0.1.6-py3-none-any.whl
| Download URL | courser-0.1.6-py3-none-any.whl |
|---|---|
| Size | 99.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6d7dca816cc559aec143f71225a8a39ac910bf36d67f7b38ec6e4b23c76ac703
|
|
BLAKE2b-256 checksum How to use checksums |
f1e8d16b333e4aab675eae87682d6f9444fca30fae8113eee85665d4f0d65401
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|