BBCOJ 题目获取

我们时常遇到这样的问题:其他同学都已经解锁题单并做起来了,但是我们却仍然没有解锁题单。这个时候,内向的同学们想必一定不敢寻找老师帮忙,于是我们需要自给自足。

这个时候,我们就会想着直接爆破题单密码不就行了。

基于此想法,我们开发了题单密码爆破器,利用多进程多线程对 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}&currentPage=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}&currentPage=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 []

BBCOJ 题目获取
https://lzj-blog.top/2026/02/04/BBCOJ-题目获取/
作者
starfallen
发布于
February 4, 2026
许可协议