news 2026/1/24 6:07:03

Python爬取科目一题库1685道实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python爬取科目一题库1685道实战

Python爬取科目一题库1685道实战

在准备机动车驾驶人考试时,很多人都会面临这样一个问题:市面上的驾考App虽然功能齐全,但大多只能在线刷题,无法批量导出题目用于离线学习或系统整理。更别提把所有题目做成一份完整的复习资料了——这几乎是每个学员梦寐以求的事。

有没有可能用技术手段一次性获取全部官方题库?答案是肯定的。通过简单的网络请求分析和Python脚本编写,我们完全可以实现对“驾驶员考试网”科目一1685道题目的自动化抓取,并生成图文并茂的Word文档,供随时查阅与打印。

整个过程并不复杂,也不需要高深的技术背景。只要你熟悉基本的Python语法,就能轻松上手。接下来,我们就从零开始,一步步拆解这个看似“黑科技”的爬虫项目。


进入目标网站 m.jsyks.com/km1_sxlx 后,点击“顺序练习”,你会发现页面加载第一道题后,后续切换题目时页面并没有刷新。这种流畅的体验背后,其实是典型的前后端分离架构:前端通过JavaScript异步请求后台接口,动态更新内容。

打开浏览器开发者工具(F12),切换到Network标签页,然后连续点击几次“下一题”。很快你就会发现一个规律性的请求:

https://tkdata.mnks.cn/ExamData/{code}.json?CALL=?{version}.json

其中{code}是每道题的唯一标识符,而{version}则是当前题库的版本号。这些数据以JSON格式返回,结构清晰、字段明确,简直是为爬虫量身定制的接口。

响应体示例如下:

{ "tkId": 2013, "sortId": 1501, "cx": "xc,hc,kc", "code": "3fd79", "tx": 1, "tm": "驾驶机动车在道路上违反道路通行规定应当接受相应的处罚。", "da": "对", "tv": "", "tags": "违反道路通行规定" }

关键字段含义如下:

字段说明
tm题干内容,包含<br/>换行标签
da正确答案
tx题型:1=判断题,2=单选题,3=多选题
tv图片路径编码(如有)
code题目ID

对于判断题来说,处理起来最简单,题干直接就是文本,答案也只有“对”或“错”。但选择题稍微复杂一些,它的选项通常嵌在tm中,用<br/>分隔。比如:

夜间会车应当在距相对方向来车多少米以外改用近光灯? <br/>A. 50米 <br/>B. 100米 <br/>C. 150米 <br/>D. 200米

这时候就需要用.split('<br/>')将其拆分成题干和选项两部分。

部分题目还配有示意图,比如交通标志、车道指示等,这些图片信息存储在tv字段中,形如/SU/od50vqgFW8x。去掉前缀/SU/,拼接到固定域名即可得到真实地址:

https://sucimg.itc.cn/sblog/od50vqgFW8x

该链接可直接下载PNG格式图片,质量清晰,适合插入文档使用。

要实现全量抓取,光知道单个题目的接口还不够,还得拿到全部1685个题目的code列表。这些数据并没有藏在HTML里,而是写在一个JS文件中。通过查看网页源码,可以找到如下声明:

var ExamVersion = "20201231143735"; var ExamCount = 1685; var ExamCodes = "02dec,0d977,02567,...,fcd0b"; // 共1685个code

复制这段字符串,按逗号分割成列表,就可以遍历所有题目了。虽然题库标注的是2020年版本,但经测试至今仍有效,且内容已同步至最新考试标准。


为了运行爬虫脚本,我们需要先搭建一个干净的Python环境。推荐使用 Anaconda 管理虚拟环境:

conda create -n km1_spider python=3.9 conda activate km1_spider

安装所需依赖包:

pip install requests docx lxml urllib3

核心库说明:
-requests: 发起HTTP请求,获取JSON数据;
-urllib.request: 下载图片资源;
-docx: 写入Word文档,支持图文混排;
-lxml: 可选,用于复杂HTML解析(本例未使用);

开发工具建议使用 PyCharm 或 VS Code,便于调试和查看输出结果。整个项目无需数据库支持,所有数据均来自公开接口,非常适合初学者练手。


下面是最基础的测试代码,用于爬取前100道题并在控制台打印出来:

import requests ExamCount = 1685 ExamVersion = "20201231143735" ExamCodes = "02dec,0d977,02567,..." # 此处省略完整字符串 ExamCodes = ExamCodes.split(',') for i in range(0, 100): code = ExamCodes[i] url = f'https://tkdata.mnks.cn/ExamData/{code}.json?CALL=?{ExamVersion}.json' try: response = requests.get(url, timeout=10) data = response.json() question = data['tm'].split('<br/>') answer = data['da'] if len(question) > 1: print(f"{i+1}、{question[0]} 答案:{answer}") print(f" {question[1]} {question[2]} {question[3]} {question[4]}") else: print(f"{i+1}、{question[0]} 答案:{answer}") if data['tv']: img_url = 'https://sucimg.itc.cn/sblog/' + data['tv'].split('/')[-1] print(f" [图片] {img_url}") except Exception as e: print(f"第{i+1}题抓取失败: {e}")

运行效果:控制台依次输出前100道题的题干、选项和答案,若存在配图则显示图片URL。这是验证接口可用性和逻辑正确性的第一步。


真正实用的是将全部1685道题导出为Word文档,方便打印、分享或导入其他学习软件。以下是完整实现代码:

import requests import time from docx import Document from docx.shared import Pt, Inches from docx.enum.text import WD_PARAGRAPH_ALIGNMENT import urllib.request import os # 创建图片存储目录 img_dir = "./km1_images" os.makedirs(img_dir, exist_ok=True) def download_image(img_path, save_name): try: full_url = 'https://sucimg.itc.cn/sblog/' + img_path.split('/')[-1] save_path = os.path.join(img_dir, f"{save_name}.png") urllib.request.urlretrieve(full_url, save_path) return save_path except Exception as e: print(f"图片下载失败: {e}") return None # 初始化Word文档 doc = Document() doc.add_heading('机动车驾驶人科目一题库(1685道)', level=1) doc.add_paragraph("来源:驾驶员考试网 | 生成时间:" + time.strftime("%Y-%m-%d %H:%M")) ExamVersion = "20201231143735" ExamCodes = "02dec,0d977,02567,..." # 实际使用请补全 ExamCodes = ExamCodes.split(',') headers = {'User-Agent': 'Mozilla/5.0'} for idx, code in enumerate(ExamCodes): url = f'https://tkdata.mnks.cn/ExamData/{code}.json?CALL=?{ExamVersion}.json' try: resp = requests.get(url, headers=headers, timeout=15) data = resp.json() q_text = data['tm'].replace('<br/>', '\n').strip() options = q_text.split('\n')[1:] if '\n' in q_text else [] main_q = q_text.split('\n')[0] p = doc.add_paragraph() runner = p.add_run(f"{idx+1}、{main_q} 【答案】:{data['da']}\n") runner.bold = True for opt in options: if opt.strip(): doc.add_paragraph(f" {opt}", style='List Bullet') if data['tv']: img_save_path = download_image(data['tv'], f"img_{idx+1}") if img_save_path: paragraph = doc.add_paragraph() paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER run = paragraph.add_run() run.add_picture(img_save_path, width=Inches(4)) time.sleep(0.5) # 控制请求频率,避免被封IP except Exception as e: print(f"第{idx+1}题抓取异常: {e}") # 保存文档 output_path = "科目一题库1685道.docx" doc.save(output_path) print(f"\n✅ 全部题目已成功导出至:{output_path}")

几点关键设计考虑:

  • 自动创建km1_images文件夹存放下载的图片;
  • 每道题标题加粗显示,答案突出标注;
  • 选项使用项目符号列出,结构清晰;
  • 图片居中插入,宽度设为4英寸,适配A4纸张;
  • 设置User-Agenttime.sleep(0.5)防反爬;
  • 最终生成.docx文件,兼容性好,支持跨平台查看。

运行完成后,你会得到一个超过200页的完整题库文档,带图、带答案,结构规整,完全可以作为备考主力资料使用。


有些题目还附带官方解析,存放在另一个接口中:

https://tkdata.mnks.cn/ExamNote/{code}.json?CALL=?{version}.json

返回的是JSON数组,cnt字段即为解析内容。但由于服务器返回的数据中可能包含非法字符(如开头的?),需要做预处理才能正常解析。

以下是一个获取前20道题解析的示例代码:

import requests import json ExamCodes = "02dec,0d977,02567,..." # 同上 ExamCodes = ExamCodes.split(',') ExamVersion = "20201231143735" for i, code in enumerate(ExamCodes[:20]): url = f'https://tkdata.mnks.cn/ExamNote/{code}.json?CALL=?{ExamVersion}.json' try: resp = requests.get(url, timeout=10) # 移除非法前缀 "?" 并解析JSON text = resp.text.lstrip('?') notes = json.loads(text) if notes and isinstance(notes, list): print(f"{i+1}、{notes[0]['cnt']}") else: print(f"{i+1}、暂无解析") except Exception as e: print(f"{i+1}、解析获取失败: {e}")

⚠️ 注意:json.loads()默认不允许非标准JSON格式,因此必须先去除开头的?字符。也可以使用strict=False参数放宽限制,但建议显式清理更稳妥。


整个项目的实现过程展示了如何通过逆向分析前端请求,快速定位数据接口,并利用Python高效采集结构化数据。它不仅适用于驾考题库,也为处理类似静态资源型Web应用提供了通用思路。

值得注意的是,这类接口之所以能长期稳定存在,往往是因为它们服务于移动端或小程序,出于性能考虑采用了轻量级JSON通信方式。只要不频繁请求、不恶意攻击,一般不会触发风控机制。

当然,也要提醒大家:请勿将爬取内容用于商业牟利,尊重原网站版权与服务条款。技术本身无善恶,关键在于使用者的目的与边界。

如果你有兴趣,还可以进一步拓展功能,比如:
- 将Word转为PDF,便于手机阅读;
- 构建本地SQLite数据库,支持模糊搜索;
- 接入AI模型,自动生成错题讲解;
- 开发微信小程序,实现个性化刷题。

这才是技术真正有趣的地方——不只是“能做什么”,而是“还能怎么做”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/20 20:56:03

解析 ‘PREEMPT_RT’ 补丁:如何将通用 Linux 改造为具备确定性响应的硬实时内核?

各位同仁&#xff0c;各位对系统编程与实时控制充满热情的工程师们&#xff1a;欢迎来到今天的讲座&#xff0c;我们将深入探讨一个在工业控制、航空航天、医疗设备以及高性能计算领域至关重要的技术——如何将我们熟悉的通用 Linux 操作系统改造为具备确定性响应的硬实时内核。…

作者头像 李华
网站建设 2026/1/22 14:38:57

Spark集群搭建与PySpark开发环境配置

Spark集群搭建与PySpark开发环境配置 在大数据处理日益成为企业核心能力的今天&#xff0c;构建一个稳定高效的分布式计算平台是开展数据分析、机器学习乃至大模型工程化的基础。Apache Spark 作为当前最主流的统一分析引擎&#xff0c;其快速、易用和通用的特点让它广泛应用于…

作者头像 李华
网站建设 2026/1/20 23:10:50

JSP+JavaScript 实现验证码登录功能

JSP JavaScript 实现验证码登录功能 在开发一个 Web 应用时&#xff0c;用户登录几乎是每个系统都绕不开的环节。而为了防止恶意程序暴力破解密码&#xff0c;加入图形验证码成了最基础、也最有效的防护手段之一。最近我在做 Java Web 练手项目时&#xff0c;就动手实现了一套…

作者头像 李华
网站建设 2026/1/21 23:32:38

Docker从入门到实践:核心概念与实战指南

Docker从入门到实践&#xff1a;核心概念与实战指南 在现代AI开发中&#xff0c;一个令人头疼的场景再熟悉不过&#xff1a;你在本地调试好的多模态模型&#xff0c;一放到服务器上就“水土不服”——依赖版本冲突、CUDA环境不匹配、Python包缺失……尤其是像 GLM-4.6V-Flash-…

作者头像 李华
网站建设 2026/1/17 14:17:29

CI/CD工具一文纵评,GitLab CI/CD vs Jenkins vs Arbess

面对众多的CI/CD工具&#xff0c;如何根据功能、价格和易用性做出选择&#xff1f;本文旨在通过多款工具的横向对比&#xff0c;为你提供清晰的梳理与参考。1、GitLab CI/CD1.1 产品介绍GitLab CI/CD 是 GitLab 内置的自动化工具链&#xff0c;提供从代码提交到生产部署的全流程…

作者头像 李华
网站建设 2026/1/20 19:42:25

【Open-AutoGLM操作手机安装全攻略】:手把手教你5步完成部署

第一章&#xff1a;Open-AutoGLM操作手机安装全解析Open-AutoGLM 是一款基于大语言模型驱动的移动端自动化工具&#xff0c;支持通过自然语言指令控制手机完成各类操作。其核心优势在于无需编写代码即可实现应用启动、页面跳转、数据填写等自动化流程。以下为在安卓设备上部署并…

作者头像 李华