自建科目一刷题系统:FastAPI+SQLite实现本地题库管理,模拟考试与错题本一体搞定

发布时间:2026/8/30 5:15:46
自建科目一刷题系统:FastAPI+SQLite实现本地题库管理,模拟考试与错题本一体搞定 “科目一离开的太快就像龙卷风”这句调侃最近在驾考群、刷题帖里经常看到。科目一考完的轻松感是真的但考前反复刷题的焦虑也是真的。如果你还在一个题库不全、广告不少、数据不能导出的刷题 App 里硬啃交规今天这篇不是给你讲记忆口诀而是给你一套可以自己部署的科目一刷题服务题库导入、顺序练习、模拟考试、错题本、成绩统计、API 调用和批量任务全部放在自己手里。数据是你的题目是你的错题记录也是你的再也不用担心“App 改版后我的收藏没了”。这类本地刷题系统其实不复杂核心就是“题库数据 练习/考试逻辑 一个轻量 Web 界面”。技术栈可以选 FastAPI、Flask、Node.js Express 等常用框架数据库用 SQLite 起步后续题库量大了再迁 MySQL 或 PostgreSQL。整个项目对硬件要求很低不需要 GPU不需要高配主机几年前的电脑、一台闲置小主机、甚至树莓派都能跑。下面我会按“能力速览 - 环境准备 - 安装部署 - 功能测试 - API 与批量任务 - 资源占用 - 排错 - 最佳实践”的顺序完整展开。1. 核心能力速览能力项说明项目类型驾考理论刷题 / 在线模拟考试 / 题库管理系统技术栈建议Python FastAPI 或 FlaskNode.js Express数据库 SQLite/PostgreSQL核心功能顺序刷题、随机练习、模拟考试、错题本、成绩统计、题库导入导出、OCR 识题扩展硬件需求CPU 双核及以上内存 4G 以上磁盘 2G 以上即可无 GPU 需求性能特点轻量服务单机使用内存占用很小1 万题以内 SQLite 足够支持平台Windows、Linux、macOS支持 Docker 部署启动方式命令行启动 / Docker 启动 / 脚本一键启动API 能力REST JSON 接口支持题目查询、生成试卷、答案判分、批量导入导出批量任务支持题库批量导入、错题批量导出、成绩统计导出、批量生成模拟卷适合场景学员自建刷题环境、驾校内部模拟平台、软件工程课程设计、基于题库的二次开发这套方案最大的价值不是“做一个 App”而是把刷题过程变成一套可维护、可扩展、可编程的系统。你可以把官方或授权的题库导入 SQLite让学员通过浏览器刷题同时把每次练习的答题记录、错题、得分都留存下来。后续想加“按章节练习”“高频错题复习”“每日一考”都只是加接口和页面的问题。2. 适用场景与使用边界2.1 适合谁用备考科目一或科目四的学员想在电脑上集中刷题而不是一直盯手机小屏幕顺便保留自己的错题记录。驾校或培训机构需要给内部学员提供一个简单的模拟考试环境统计班级练习情况。想做毕设或课程设计的开发者一套完整的刷题系统很适合作为 Web 开发项目覆盖增删改查、文件导入、接口设计、数据统计等常见模块。有二次开发需求的人题库数据可以用接口批量读取方便接入自己的学习计划、提醒脚本或小程序前端。2.2 能解决的问题避免第三方平台题库变动导致的历史记录丢失。支持自定义题库比如把地方性法规题目、新规题目单独维护。支持离线或内网部署训练场、自习室等无外网环境也能用。通过 API 方式批量管理题目比手工整理 Word 文档高效得多。2.3 不适合什么场景不适合做大规模公开在线考试平台因为没有用户体系、权限分级、防作弊、高并发压测等设计直接公网开放在安全性上风险较大。不适合直接抓取或二次分发未经授权的题库。科目一题库内容有版权和时效性要求题目来源必须合法授权导入前要确认数据合规性。不适合作为替代交管官方考试的唯一依据平台上的题应当定期与官方题库版本同步。2.4 版权与安全边界科目一题目本身涉及交通运输法规和版权内容不要从黑灰产渠道购买所谓“内部题库”“包过题库”。建议使用官方公开题库、授权数据或自行整理的合规题目。如果系统要部署到公网必须做访问控制避免题库数据和学员答题记录泄露。涉及个人练习数据时还要注意隐私保护不能随意导出他人信息。3. 环境准备与前置条件3.1 硬件与操作系统系统本身很轻推荐配置如下实际可以更低CPU双核以上即可刷题接口不是计算密集型任务。内存4G 以上如果并发量不大2G 也能跑。磁盘系统 2G 左右题库数据看规模1 万道题加上索引一般几十 MB。操作系统Windows 10/11、Ubuntu 20.04、macOS 均可。GPU不需要纯后端 Web 服务完全没有显存压力。3.2 软件依赖选择 Python 技术栈时建议用 Python 3.10 以上版本。如果选择 Node.js 技术栈建议 Node.js 18 以上。数据库优先选 SQLite因为零配置、单文件、备份方便当题库超过几十万条且并发明显变高时再换 PostgreSQL。必装软件清单Python 3.10 或 Node.js 18 pip 或 npm Git可选用于拉取代码 Docker可选用于容器化部署 SQLite3Python 自带不需要额外安装3.3 目录结构规划建议提前把目录规划好否则后续题库文件、导出文件、数据库文件混在一起维护成本很高。参考结构如下driving-exam/ ├── app.py # 主入口启动 Web 服务 ├── requirements.txt # Python 依赖 ├── data/ │ ├── questions.db # SQLite 数据库文件 │ ├── raw/ # 原始题库文件如 Excel/CSV/JSON │ └── exports/ # 导出结果如错题、成绩单 ├── static/ # 前端静态文件 ├── templates/ # 页面模板 └── scripts/ ├── import_questions.py # 批量导入脚本 └── generate_exam.py # 批量生成模拟卷脚本目录规划的原则是程序代码和业务数据分开原始文件和导出文件分开让备份和清理都更简单。4. 安装部署与启动方式4.1 获取项目代码如果项目已发布到 Git 仓库直接拉取git clone https://github.com/yourname/driving-exam.git cd driving-exam如果暂时没有代码仓库可以自己按上面的目录结构创建项目后续依赖和启动命令是一样的。从零创建时可以使用 FastAPI 作为 Web 框架理由是对 API 支持好、文档自动生成方便和后面的批量任务脚本对接。4.2 创建虚拟环境并安装依赖Python 项目强烈建议使用虚拟环境避免污染系统全局环境。# 在项目目录下执行 python -m venv venv # Windows venv\Scripts\activate # Linux / macOS source venv/bin/activate依赖文件 requirements.txt 内容按实际框架填写核心依赖包括fastapi uvicorn pandas openpyxl python-multipart安装依赖pip install -r requirements.txt如果使用 Node.js 技术栈则执行npm init -y npm install express better-sqlite3 multer依赖安装失败时先检查网络源国内环境可以切换到国内镜像源再重试。4.3 初始化题库数据库首次启动前需要初始化数据表。假设题库表结构如下questions 表题目 ID、章节、题型、题干、选项 A-D、正确答案、解析。exam_records 表考试记录包含用户、得分、总题数、正确数、答题时间。wrong_questions 表错题记录包含用户、题目 ID、错误次数、最后错误时间。初始化 SQL 示例CREATE TABLE IF NOT EXISTS questions ( id INTEGER PRIMARY KEY AUTOINCREMENT, chapter TEXT, type TEXT, question TEXT NOT NULL, option_a TEXT, option_b TEXT, option_c TEXT, option_d TEXT, answer TEXT NOT NULL, analysis TEXT ); CREATE TABLE IF NOT EXISTS wrong_questions ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_name TEXT, question_id INTEGER, wrong_count INTEGER DEFAULT 1, last_wrong_time TEXT );在项目里可以写一个 scripts/init_db.py运行一次即可。4.4 启动服务以 FastAPI 为例启动命令如下uvicorn app:app --host 0.0.0.0 --port 8080如果只想本机访问把地址改成 127.0.0.1uvicorn app:app --host 127.0.0.1 --port 8080启动成功后浏览器打开 http://127.0.0.1:8080 能看到刷题系统首页或接口文档页面。如果页面打不开先看终端日志是否有报错再用以下命令确认端口是否被占用# Windows netstat -ano | findstr :8080 # Linux / macOS lsof -i :80804.5 Docker 启动如果不想在宿主机装 Python 环境可以用 DockerFROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple COPY . . EXPOSE 8080 CMD [uvicorn, app:app, --host, 0.0.0.0, --port, 8080]构建并启动docker build -t driving-exam . docker run -d -p 8080:8080 -v $(pwd)/data:/app/data driving-exam这里把本机 data 目录挂载到容器数据库和导出文件不会因为容器重建而丢失。5. 功能测试与效果验证系统启动后建议按下面的顺序做一轮完整验证。先不要急着导入大量题目先用 10 到 20 道测试题跑通流程再导入完整题库。5.1 基础刷题测试测试目的确认题目能正常读取答题流程没有 Bug。操作步骤准备 10 道测试题通过管理页面或接口导入。打开刷题页面选择“顺序练习”。逐题作答选择正确答案。查看解析是否显示正常。判断标准题目顺序和数据库顺序一致点击选项能记录答案查看解析能看到内容。如果题目乱码检查数据库连接字符集和 CSV 文件编码建议统一使用 UTF-8。5.2 随机练习测试测试目的验证随机选题逻辑和重复控制。操作步骤在刷题页面选择“随机练习”模式。连续生成多组题目观察题目顺序是否变化。确认单次练习内不会重复出同一道题。预期结果每次生成的 10 题或 20 题组合都不同同一轮内题目不重复。如果发现重复说明随机查询语句没有去重检查 SQL 里的 ORDER BY RANDOM() 是否配合了题量限制。5.3 模拟考试测试测试目的验证自动组卷、计时、交卷判分三个关键逻辑。操作步骤选择模拟考试设置题目数量为 50 或 100。设置考试时间比如 45 分钟。开始答题中途故意做错几题。交卷后查看得分、正确答案和错题列表。判断标准试卷包含的题目数量符合设置值。交卷后得分计算正确每题分值按“100 分 / 总题数”得出。错题自动写入错题本。时间耗尽后系统能强制交卷并保存记录。这里最容易出问题的是“时间到了没交卷”需要在后端做时间校验不能只靠前端倒计时。前端倒计时归零后必须调用一次交卷接口把当次答题数据存下来。5.4 错题本测试测试目的确认错题记录能累积、能重新练习、能导出。操作步骤做错 3 道题。打开错题本确认 3 道错题都在。再次做对其中 1 道观察错题记录变化。导出错题列表确认导出文件可读。判断标准错题本中每道题有错误次数做对后可以保留记录也可以设置“连续做对 3 次自动移除”具体看产品设计。导出文件建议同时提供 CSV 和 Excel 两种格式方便学员打印复习。5.5 批量题库导入测试这是整个系统最值得重点测试的功能。科目一题库动辄上千道题不可能手工录入。批量导入支持以下格式CSV 文件字段chapter,type,question,option_a,option_b,option_c,option_d,answer,analysisExcel 文件xlsx 格式列名与 CSV 一致JSON 文件数组形式CSV 示例chapter,type,question,option_a,option_b,option_c,option_d,answer,analysis 驾驶证章节,单选题,驾驶机动车在道路上违反道路交通安全法的行为属于什么行为?,违章行为,违法行为,违规行为,过失行为,B,违反道路交通安全法属于违法行为 导入脚本示例 python import pandas as pd import sqlite3 def import_csv_to_db(csv_path, db_path): df pd.read_csv(csv_path) conn sqlite3.connect(db_path) df.to_sql(questions, conn, if_existsappend, indexFalse) conn.close() print(f导入完成共 {len(df)} 条) if __name__ __main__: import_csv_to_db(data/raw/questions.csv, data/questions.db)导入后的校验逻辑很关键必填字段不能为空。answer 只能是 A/B/C/D。同一道题不能重复入库可以在题干上建唯一索引。导入后统计总数确认和源文件行数一致。5.6 OCR 识题扩展测试如果你想把纸质教材或图片截图里的题目转成结构化数据可以加一个 OCR 功能。这里建议使用 PaddleOCR 或 Tesseract识别完成后把文本再按规则拆分到题目字段。OCR 流程上传题目截图。调用 OCR 接口识别文字。把识别结果按“题干 选项 答案”的规则拆分。进入人工校对页面确认后写入题库。注意OCR 识别率不可能 100%尤其是判断题里的“对/错”和多选题。只能把 OCR 当成辅助录入工具不能跳过人工审核。6. 接口 API 与批量任务这套系统如果只是网页刷题价值有限。真正好用的是把核心能力全部接口化这样后面可以做小程序、定时任务、数据统计脚本。6.1 查询题目接口请求示例curl http://127.0.0.1:8080/api/questions?limit10offset0返回示例{ total: 1000, items: [ { id: 1, chapter: 驾驶证章节, type: 单选题, question: 驾驶机动车在道路上违反道路交通安全法的行为属于什么行为?, option_a: 违章行为, option_b: 违法行为, option_c: 违规行为, option_d: 过失行为, answer: B, analysis: 违反道路交通安全法属于违法行为 } ] }接口实现时注意两点一是不要每次都把解析字段返回给刷题过程练习时可以在判分后再返回解析二是列表接口要做分页避免一次返回几千条拖慢页面。6.2 生成模拟试卷接口请求参数{ chapter: 全部, question_count: 50, random: true }示例curl -X POST http://127.0.0.1:8080/api/exam/generate \ -H Content-Type: application/json \ -d {chapter: 全部, question_count: 50, random: true}系统生成一张试卷返回试卷 ID 和题目列表。答题时前端只显示题干和选项不返回 answer 字段防止直接看接口答案。6.3 提交答案与判分接口curl -X POST http://127.0.0.1:8080/api/exam/submit \ -H Content-Type: application/json \ -d {exam_id: 1001, answers: [{question_id: 1, answer: B}, {question_id: 2, answer: C}]}返回结果{ score: 96, total: 50, correct: 48, wrong_list: [ { question_id: 2, question: 题目内容, your_answer: C, correct_answer: D, analysis: 解析内容 } ] }判分接口一定要做幂等处理用户重复点交卷多次不重复写入多条考试记录。可以用 exam_id 加唯一约束实现。6.4 批量导入接口上传文件到导入接口curl -X POST http://127.0.0.1:8080/api/questions/import \ -F filedata/raw/questions.xlsx返回导入结果{ total: 1000, success: 998, failed: 2, errors: [ {row: 55, reason: answer 字段为空}, {row: 156, reason: 题干重复} ] }批量导入建议采用“先校验再入库”的策略先把文件读入内存逐行检查字段全部通过后只执行一次批量插入这样避免导入到一半失败导致数据不完整。6.5 批量导出错题与成绩把错题导出为 CSVcurl -X GET http://127.0.0.1:8080/api/export/wrong-questions?user_nametomformatcsv \ -o wrong_questions.csv把成绩统计导出为 Excelcurl -X GET http://127.0.0.1:8080/api/export/scores?date_from2025-01-01date_to2025-12-31formatxlsx \ -o scores.xlsx导出功能对驾校管理员很实用。每周跑一次批量导出就能掌握学员的练习情况哪些章节错误率高、哪些学员需要重点辅导、整体平均分有没有提升。6.6 批量生成模拟卷脚本可以写一个 Python 脚本每天早上自动生成一套 100 题模拟卷并推送链接到企业微信群或钉钉群。import requests import datetime api_base http://127.0.0.1:8080/api today datetime.date.today().strftime(%Y-%m-%d) def generate_daily_exam(): payload { chapter: 全部, question_count: 100, random: True } resp requests.post(f{api_base}/exam/generate, jsonpayload, timeout10) exam_id resp.json().get(exam_id) print(f{today} 模拟卷已生成考试 ID{exam_id}) if __name__ __main__: generate_daily_exam()批量任务要注意失败重试。比如接口超时、数据库锁、网络抖动都可能让任务中断。建议增加简单的重试机制失败后等待 5 秒再重试一次连续失败则写入日志并发送告警。7. 资源占用与性能观察7.1 如何观察资源占用启动服务后在另一个终端窗口观察进程占用# Linux / macOS ps aux | grep uvicorn top -p $(pgrep -f uvicorn | head -1) # Windows 任务管理器按 CPU 和内存排序查看 python 进程对于单人刷题或驾校内网二三十人使用的场景这类轻量服务的内存占用通常不会高。但具体数字取决于框架、题库数据量、并发连接数和日志输出级别不能一概而论建议在自己机器上跑一遍完整刷题流程后再统计真实占用。7.2 题库规模与数据库选型科目一题库一般在 1000 到 2000 题左右加上答案解析SQLite 单文件完全够用。查询时按章节过滤题目要建 chapter 索引。按题目去重要在 question 字段上建唯一索引。查询错题按 user_name 过滤要建 user_name 索引。如果题库规模到了几十万条或开始做多用户高并发在线考试建议切换到 PostgreSQL并启用连接池。7.3 并发与公网部署本地单机使用不需要考虑高并发。但如果部署到公网建议前面加 Nginx 反向代理配置 HTTPS。服务本身只监听 127.0.0.1由 Nginx 转发到 8080 端口。对 /api 路径做访问频率限制防止题库被爬虫批量拉走。考试交卷接口要限制单用户提交频率。7.4 性能优化建议分页查询列表接口绝对不要一次返回全表。批量插入导入题库时用 executemany 或 to_sql不要一条条 insert。缓存章节列表章节信息变化频率低可以缓存 10 分钟。慢查询日志如果页面变卡先看 SQLite 是否出现锁等待。8. 常见问题与排查方法问题现象可能原因排查方式解决方案浏览器打不开服务页面服务未启动、端口被占、防火墙拦截查看终端日志执行 netstat 或 lsof 检查端口换端口或重启服务题库导入后中文乱码CSV 编码不是 UTF-8用文本编辑器打开 CSV 查看编码统一转换为 UTF-8 后重新导入pip install 安装失败网络源不稳定或依赖冲突查看报错信息确认当前虚拟环境是否激活切换国内镜像源重建虚拟环境数据库提示 database is lockedSQLite 写并发冲突查看是否有多个进程同时写数据库改用 WAL 模式或加连接锁OCR 识别答案错误图片模糊、字体不规范检查识别文本与题干是否对齐增加人工校对步骤调整图片预处理交卷后成绩没保存前端超时或接口异常查看浏览器开发者工具 Network 面板在交卷接口增加超时重试和日志模拟卷题目重复随机查询没有去重检查生成试卷 SQL使用临时表或先取题号集合再查题干接口返回 500代码异常、参数错误查看后端日志堆栈根据堆栈修复对应代码这套排查思路其实对所有轻量 Web 系统都适用先看日志再确认进程端口再检查数据最后定位代码逻辑。不要一上来就怀疑硬件和网络绝大多数问题出在编码、端口、依赖版本和数据库状态这四类地方。9. 最佳实践与使用建议9.1 先准备好一套最小可运行配置不要把题库、数据库、导出文件全部塞在项目根目录。建议第一次运行前先按 demo 模式跑通只导入 20 道测试题确认页面和接口正常后再导入正式题库。这样即使后面配置出错也不会污染正式数据。9.2 题库文件与数据库分开管理原始题库 Excel/CSV 是源头数据库是运行时数据导出文件是结果。三者分开后每次题库更新流程就变成“修改源文件 - 校验 - 导入 - 导出备份”如果导入出问题直接用上一次的数据库备份恢复即可。9.3 建立自动备份机制SQLite 备份很简单直接复制 .db 文件即可。可以写一个定时任务每天凌晨把 data/questions.db 和 data/exports 压缩一份。# 每天凌晨 2 点执行备份 0 2 * * * tar -czf /backup/questions_$(date \%Y\%m\%d).tar.gz -C /opt/driving-exam/data .9.4 题库来源必须合法合规科目一题库属于交通法规相关的内容上线公开部署前要确认题库来源授权。不要使用来源不明、声称“内部绝密”“包过”的数据这类数据既涉及版权问题内容准确性可能也很差。系统只作为学习辅助不作为官方考试依据。9.5 接口安全与访问控制即使只在局域网使用也建议加一层简单的访问口令。公网部署更要注意批量导入接口不能开放给匿名用户导出接口要校验权限登录和考试记录要避免明文传输。如果只是自己用最简单的方式是在 Nginx 层面加 Basic Auth。10. 总结与下一步这套自建科目一刷题系统最值得尝试的点在于把“刷题”从依赖第三方 App 变成完全可控的本地服务。数据在自己手里批量导入导出方便还有 API 能对接自动化脚本。如果你正准备做一个 Web 开发练手项目它也是一个很好的综合案例数据库设计、文件导入、接口开发、前端页面、定时任务全都能覆盖。建议最先验证的是“模拟考试 错题本”这两个功能直接决定学习体验最容易踩的坑是题库导入时的编码问题和数据库并发锁问题都是老生常谈但反复出现的坑。后续可以继续扩展的方向包括微信小程序端、错题遗忘曲线提醒、成绩趋势图表、多人账号体系以及把 OCR 识题流程做得更自动化。“科目一离开的太快就像龙卷风”是考过之后的一种感慨但如果你把整个刷题系统部署在自己的服务器上想什么时候练、怎么练、数据怎么用都是自己说了算。这比刷完就忘的临时 App 体验要踏实得多。

相关新闻