本文最后更新于 2026-02-04T12:49:14+08:00
我们时常遇到这样的问题:其他同学都已经解锁题单并做起来了,但是我们却仍然没有解锁题单。这个时候,内向的同学们想必一定不敢寻找老师帮忙,于是我们需要自给自足。
这个时候,我们就会想着直接爆破题单密码不就行了。
基于此想法,我们开发了题单密码爆破器,利用多进程多线程对 BBCOJ
的题单密码进行爆破,并成功攻克十几个题单密码。
但是很快,BBCOJ
的服务器就被我们的请求和日志塞满了,导致老师来对我们发出质疑,并使用退队警告,于是,我们需要一个更加优雅的方式来做题。
我们看,爆破题单密码的本质目的是什么?不就是为了获取题单内部的题目吗,于是我们将目光放在
BBCOJ
的题目的另一个属性上:标签。我们发现同一类题目都具有同一种标签,而我们可以使用
BBCOJ 的 API 端口进行获取同一标签下的所有题目。
基于此理论,我开发了一种基于标签的题目搜索方法,它具有以下优点:
- 对服务器压力小。我的程序加入了缓存机制,对于同一标签,不会反复获取。同时,一次请求的返回量仅相当于一次请求题单排名,压力小于一名普通做题同学。
- 不使用非法连接。我的程序所使用的全都是 BBCOJ
官方对外接口,未出现访问非法接口的问题。
- 无不良影响。它只能给出题目,不能给同学其他的娱乐方式,不会让同学沉迷。
本工具使用 AI 辅助开发,于 Github 上开源。
核心代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| def fetch_problems_by_tag(tag_id): if tag_id in cache: return cache[tag_id] try: headers = login() url1 = f'{base_url}/api/get-problem-list?oj=Mine&tagId={tag_id}¤tPage=1&limit=1' response1 = fet.get(url1, headers=headers) data1 = response1.json() tsize = data1["data"]["total"] print(f'标签 {tag_id}: 共计 {tsize} 题,正在爬取……') url2 = f'{base_url}/api/get-problem-list?oj=Mine&tagId={tag_id}¤tPage=1&limit={tsize}' response2 = fet.get(url2, headers=headers) problems_data = response2.json() problems = [] for cur in problems_data["data"]["records"]: problems.append({ 'id': cur["problemId"], 'title': cur["title"] }) cache[tag_id] = problems return problems except Exception as e: print(f'获取题单失败: {e}') return []
|