【开源】STAL 洛谷比赛订阅
Good morning.
很多同学都遇到过错过比赛的情况——明明是一次既能提升自己、又能增加等级分和估值的大好机会,却因为忘记比赛开始时间而失之交臂。
为了解决这一问题,现推出 STAL 洛谷比赛订阅系统,让它成为您竞赛路上最准时的管家。想直接上手,请看下面的「快速开始」与「使用方法」;想自行配置、了解内部实现,可访问 GitHub 查看详情。
快速开始
1. 准备
需要 Node.js 18 或更高版本。
git clone https://github.com/stellalling/stal.git stal
cd stal
node server.js
打开 http://127.0.0.1:3000,第一个注册的账号自动成为管理员。
首次启动时如果没有 config.json,程序会自动用 config.example.json 加一个随机生成的 sessionSecret 创建一份。
2. 配置 SMTP
以 QQ 邮箱为例。
方式一:改 config.json
{
"smtp": {
"host": "smtp.qq.com",
"port": 465,
"user": "你的QQ号@qq.com",
"pass": "你的QQ邮箱授权码",
"fromName": "洛谷比赛订阅"
}
}
方式二:网页——登录后进 /admin →「SMTP / 推送配置」→ 填地址与授权码 → 保存 → 点「测试 SMTP 登录」。
3. 常驻运行
程序自带定时任务,所以只需要让一个进程长驻,不需要额外的 cron。
# 先把 docker-compose.yml 的 STAL_SMTP_USER / STAL_SMTP_PASS 换成真值
docker compose up -d --build
对外服务建议套一层 Nginx 并启用 HTTPS。反代必须传 X-Forwarded-Proto,程序靠它判断这一跳是不是 HTTPS,才决定给会话 Cookie 加 Secure:
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
4. 验收
curl -s http://127.0.0.1:3000/api/health # {"ok":true,...}
npm run crawl # 抓一次数据
npm run send:dry # 演练今晚会推给谁、推几场
再在主页点「发送测试邮件」确认自己能收到,就大功告成了。
使用方法
如果不想自己部署,直接访问 stal.luogu.best,用邮箱注册登录后:
- 在主页看比赛列表,按状态、类型、赛制、Rated 筛选;
- 在「我的订阅设置」勾选接收范围(官方 / Rated / 团队 / 个人等)、赛制和关键词,填好收件邮箱并保存;
- 点「发送测试邮件」确认能收到信;
- 右侧「明日预告」可以提前看到明天有哪些比赛会推给你;
- 每天 20:00 自动发送邮件提醒。
请注意,本服务为公益性质的便民服务,请勿对其可靠性提出过高要求。
实现原理
那么,STAL 是怎么拿到洛谷的比赛信息的?
首先,容易发现洛谷的比赛列表中包含所有比赛信息。访问 https://www.luogu.com.cn/contest/list 时,在请求头中带上 x-lentille-request: content-only,即可直接获得 JSON 响应,稍加处理即可使用。
列表按开赛时间倒序返回。若发现某一页中最早的比赛都已开始,便停止翻页。随后获取尚未开始的比赛 ID,再通过 contest/{id} 补齐报名人数、等级分阈值和比赛说明等内容。
为减轻洛谷服务器压力,已爬取过的内容会直接复用缓存。
之后按规则打标签:
- 出题团队为“洛谷官方团队”的比赛为官方比赛;
visibility=2,4分别对应团队公开赛和个人公开赛;method=1,4,2分别对应 OI、IOI、ACM 赛制;rated !== 0即为 Rated。
最后,通过 SMTP 向用户发送邮件。
技术特点
为了少给洛谷添麻烦。
- 只要 JSON:跳过页面模板与脚本,这是最省流量的办法之一;
- 翻页早停 + 详情缓存:不翻过去的历史账,抓过的比赛不重复请求;
- 频率克制:每 1 小时一爬,每天最多 24 次列表请求;请求间隔 400ms,不并发、不制造峰值;
- 失败降级:某页失败就保留已抓数据继续,不疯狂重试;
- 数据本地化:筛选、搜索、明日预告全部走本地库,页面访问量增长压不到洛谷。
结语
STAL 比赛订阅系统将不断更新,感谢各位的支持。
AI 使用情况披露:本项目使用 DeepSeek-V4.1-Flash 辅助完成,文章由 DeepSeek-V4.1-Flash 润色。
感谢“冬日绘板 - 麦乐送计划”为本项目提供的技术支持。