Skip to main content

Course selection CLI

Project description

csniper

csniper 是一个用 Typer 实现命令行的选课工具。它把“查课、导出、解析目标、抢课”统一成 CLI 功能,抢课只是其中一个子命令。

项目约定:CLI、YAML 配置、Python 内部模型都使用规范命名;教务系统原始字段只放在 HTTP 适配层,并记录在 命名对应.md

特色功能

  • 查课、解析、抢课一体化search 用于临时查课,resolve 用于验证 courses.yaml 是否能匹配到目标任务,snipe 才负责真正提交。
  • 服务端筛选优先:查询课程号时会尽量把课程代码、教师名传给教务接口筛选,减少全页签、全分页扫描。
  • 开放时间感知:抢课前会读取教务系统页签规则里的开放时间;如果还没开放,首次提交会安排在开放时间之后 0.05 秒,而不是提前反复撞接口。
  • 克制型重试:每门课最多尝试 5 分钟;遇到频率过高时,前 5 次保持短随机间隔,第 6 次开始指数退避,随机上限控制在 30-40 秒。
  • 状态可见:等待目标时间、进入最后 10 秒、首次提交、频率限制、未开放重试、最终结果都会在终端中提示。
  • 本地配置隔离:Cookie 写在 .env,目标课写在 courses.yaml,仓库只保留样例文件,避免把个人运行配置提交出去。

安装与配置

推荐普通用户用 uv 安装 CLI:

uv tool install csniper

如果是从当前源码目录安装本地版本:

uv tool install --force .

创建一个用于放配置文件的目录,并生成配置样例:

mkdir csniper-config
cd csniper-config
csniper init

然后根据 .env.example 创建 .env,根据 courses.example.yaml 创建 courses.yaml.envcourses.yaml 是本地运行配置,不建议提交到 git。

.env 配置

登录态:

CSNIPER_SESSION_ID=
CSNIPER_ROUTE_COOKIE=

学期参数:

CSNIPER_AUTO_TERM=true
CSNIPER_ACADEMIC_YEAR=
CSNIPER_SEMESTER=
CSNIPER_TERM_CODE=
CSNIPER_CURRENT_ACADEMIC_YEAR=
CSNIPER_CURRENT_SEMESTER=
CSNIPER_CURRENT_TERM_CODE=

默认建议保持 CSNIPER_AUTO_TERM=true。程序会在首次查询前调用教务系统的当前选课学期接口,自动填充这 6 个值。只有在自动识别不符合预期时,才把 CSNIPER_AUTO_TERM=false 并手动填写这些字段。

运行参数:

CSNIPER_TARGET_TIME=2026-01-10 13:00:00
CSNIPER_CONCURRENCY=1
CSNIPER_INTERVAL_MIN=2
CSNIPER_INTERVAL_MAX=4
CSNIPER_REQUEST_TIMEOUT=20
CSNIPER_VERIFY_SSL=false
CSNIPER_QUERY_DELAY=1.5

说明:

  • CSNIPER_SESSION_ID 对应浏览器里的 JSESSIONID
  • CSNIPER_ROUTE_COOKIE 对应浏览器里的 route
  • 两个 Cookie 必须来自同一个有效浏览器会话。这两个必填,可以在浏览器开发者工具的 Cookie 中找到。
  • CSNIPER_TARGET_TIME 只影响 snipe,查询类命令不等待这个时间。
  • csniper doctor 会打印实际使用的选课学期。

目标课程配置

编辑 courses.yaml

courses:
  - course_code: ABC1234
    teacher_name: ""
    tabs: ["all"]
    match_mode: "contains"

字段含义:

  • course_code:课程代码。
  • teacher_name:教师名过滤;空字符串表示不限制教师。
  • tabs:规范页签名列表,或 ["all"] 表示扫描全部页签。
  • match_mode:课程代码匹配方式,可选 containsexact

常用写法:

tabs: ["all"]
tabs: ["compulsory"]
tabs: ["compulsory", "elective"]

内置规范页签名:

规范页签名 中文显示名
compulsory 必修
elective 限选
sports 体育
writing_communication 写作与沟通
innovation_entrepreneurship 创新创业通选课
social_practice 社会实践课
competition_guidance 竞赛指导类课程
innovation_research 创新研修
innovation_experiment 创新实验
project_based 项目制课程
retake 重修
cross_major 跨专业课程体系
liberal_arts 文理通识
mooc MOOC
optional 任选

如果教务系统出现新页签,先用 csniper tabs --live --show-system-code 查看;确认后可以写入 courses.yamlcustom_tabs

查看可用页签:

csniper tabs

需要查看教务系统编码时:

csniper tabs --show-system-code

使用当前 Cookie 从教务系统动态发现页签:

csniper tabs --live

常用命令

检查配置和登录态:

csniper doctor

查课:

csniper search ABC1234 --page-size 20
csniper search 水污染 --teacher 陈老师
csniper search ABC --tab cross_major
csniper search ABC1234 --all-matches

search 会尽量把课程代码、关键词和教师名传给教务接口做服务端筛选;查询类似 ABC1234 这种课程号时,默认在首次命中后停止扫描后续页签,以减少触发频率限制的概率。需要跨全部页签继续找同课程号时再加 --all-matches。默认不动态发现页签;确实需要刷新教务页签时使用 --live-tabs

导出课程:

csniper export --output courses_export.csv

解析 courses.yaml 中的目标课,但不提交:

csniper resolve --page-size 20

模拟抢课流程,不提交:

csniper snipe --dry-run --page-size 20

真正提交:

csniper snipe

只有不带 --dry-runsnipe 会提交选课请求。其他命令都是只读。

snipe 会先解析目标课程,再等待 CSNIPER_TARGET_TIME。如果提交后教务系统返回“未开放 / 未到选课时间”一类提示,程序会刷新一次页签规则,读取教务系统返回的开放时间,并把下一次提交安排到开放时间之后 0.05 秒。

为了避免给教务系统造成过高压力,每门课最长尝试 5 分钟。遇到“查询请求频率过高”时,前 5 次仍使用 CSNIPER_INTERVAL_MINCSNIPER_INTERVAL_MAX 的随机间隔;第 6 次开始使用指数退避,并把随机等待上限控制在 30-40 秒之间。

开发

本项目使用 uv 管理开发环境和依赖:

uv sync

编译检查:

uv run python -m compileall csniper

开发环境中运行 CLI:

uv run csniper doctor
uv run csniper search ABC1234 --page-size 20

构建发行包:

uv build
uvx twine check dist/*

主要文件:

  • csniper/cli.py:Typer 命令入口。
  • csniper/config.py:读取 .envcourses.yaml
  • csniper/client.py:HTTP 适配层,集中处理教务系统原始字段。
  • csniper/tabs.py:规范页签名和页签映射。
  • csniper/courses.py:查课、搜索、导出、目标解析。
  • csniper/sniper.py:等待时间、并发提交、响应判断。

注意事项

  • 不要提交 .env,里面包含有效登录 Cookie。
  • 不要提交 courses.yaml,里面是本地目标课程配置;仓库只保留 courses.example.yaml
  • 普通使用优先 uv tool install csniper;开发本项目时使用 uv syncuv run ...
  • 如果浏览器能访问但 csniper doctor 失败,通常是 CSNIPER_SESSION_IDCSNIPER_ROUTE_COOKIE 不匹配或已过期。
  • 遇到“查询请求频率过高”,优先缩小 --tab 范围或降低分页大小;search 内部会使用不低于 1.5 秒的查询间隔。

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

csniper-0.1.2.tar.gz (29.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

csniper-0.1.2-py3-none-any.whl (22.9 kB view details)

Uploaded Python 3

File details

Details for the file csniper-0.1.2.tar.gz.

File metadata

  • Download URL: csniper-0.1.2.tar.gz
  • Upload date:
  • Size: 29.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for csniper-0.1.2.tar.gz
Algorithm Hash digest
SHA256 156677bf67747bb674649c914b6b11f5d33a0515b256534a917dc0aba8e51de5
MD5 5beed1334df04d0228ba9ccfef7387d7
BLAKE2b-256 39caed5461050726890eaa6ac0a8b1ecbff4cf8c48ba6bdc66aae008d1af5dd0

See more details on using hashes here.

Provenance

The following attestation bundles were made for csniper-0.1.2.tar.gz:

Publisher: python-publish.yml on WyattYuan/course-sniper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file csniper-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: csniper-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 22.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for csniper-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 d2160b74b15ac5dd46cea6875d1d28c7eeefd08416c40060d5ba7d7a72fdb209
MD5 1c7a004d6c9960f8a8404c14f3244401
BLAKE2b-256 966922902787a2da1cdf0d9f77787f139811980c5c81a6bf56f450a862e2fb7c

See more details on using hashes here.

Provenance

The following attestation bundles were made for csniper-0.1.2-py3-none-any.whl:

Publisher: python-publish.yml on WyattYuan/course-sniper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page