ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

用Python将土力学PDF考试题转为结构化题库并随机抽题

用Python将土力学PDF考试题转为结构化题库并随机抽题 简介土力学考试复习题集涵盖模拟题、经典试题、名词解释、简答题与习题等常见题型适合土木工程、岩土工程等专业学生期末备考及考研复习使用。资料以单份PDF文件形式打包共1个文件容量约266KB内容紧凑便于打印或移动端阅读。目前已有74人浏览学习属于轻量型刷题资料。卷内不仅包含多道典型计算题还配有详细参考答案覆盖太沙基有效应力原理、土的破坏形式、主动与被动土压力概念、土坡失稳原因、粘性土与砂性土地基沉降差异、压缩模量与压缩系数关系推导以及饱和粘性土固结系数计算、挡土墙土压力分布和桥墩基础沉降计算等核心考点。通过模拟题与答案对照可帮助读者快速梳理土力学知识框架强化公式应用与简答记忆提升应试能力。1. 土力学考试题PDF读起来费劲不如把它变成能抽题的程序下载一套土力学考试题、模拟题、经典试题的PDF打开一看几百页名词解释、简答题、选择题、计算题混在一起想做两套模拟题得来回拖滚动条。很多人以为这种资料只能靠翻书复习实际上用Python脚本把PDF文本抽出来按题型和章节归档成结构化JSON再写个随机抽题器十分钟就能生成一套全新的土力学习题卷。这个思路适合备考注册岩土、带土力学课助教、或者帮人整理题库的工程师。本文就用这套流程把土力学习题从一个静态PDF变成一个可检索、可自测的复习库。2. 读取PDF文本先判断文件是文本层还是扫描件2.1 用PyMuPDF快速检查PDF是否自带文本层处理土力学考试题PDF的第一步是确认它到底有没有文本层。很多题库PDF是从Word直接导出的文字可以选中复制但也有一部分是纸质资料扫描后打包的看起来清晰其实每页都是一张图片。两者的处理路径完全不同花三十秒判断一下能省下后面大量的排错时间。import fitz doc fitz.open(土力学经典试题.pdf) page doc[0] text page.get_text(text) print(repr(text[:300]))这段代码用PyMuPDF打开PDF提取第一页的前300个字符。如果输出的内容是一段连贯的中文句子说明文件带文本层可以进入正则抽取阶段如果输出是空字符串或者一堆乱码那基本可以断定是扫描件只能走OCR识别路线。get_text(text)是提取纯文本换用get_text(dict)还能拿到每个文字块的坐标和字号后面按字体判断题号级别时会用到。2.2 扫描版土力学习题用pdfplumber配合OCR兜底如果是扫描件常见的做法是先用pdfplumber确认页面结构再交给OCR引擎逐页识别。pdfplumber在页面解析上比PyMuPDF更细尤其是对带有表格、公式和题号缩进的页面它能把文本块的行列关系还原得比较准确对后续分题型很有帮助。import pdfplumber with pdfplumber.open(土力学考试题.pdf) as pdf: for i, page in enumerate(pdf.pages[:3]): text page.extract_text(layoutTrue) tables page.extract_tables() print(f--- 第 {i1} 页 ---) print(text[:500]) if tables: print(发现表格, len(tables), 个)extract_text(layoutTrue)保留文本的排版位置适合处理土力学习题里那种“左边题目、右边选项”的双栏排版。extract_tables()会把页面里带框线的表格单独提取为二维数组题库末尾的答案页通常就是这种结构。对识别出来的文本不需要立刻追求完美先保证题目的编号、题干关键词完整即可后面的分类逻辑能容忍部分噪声。2.3 提取结果不完整时的三个修复点PDF文本提取最常见的坑有三个一是换行符把一句话拦腰截断二是公式里的上下标被拆成单独字符三是题目和选项之间的空格被吃掉。我的处理习惯是先把整页文本按段落重排把只有一个换行符的相邻行合并成完整段落再统一清理ASCII空格。公式乱码暂时不用管土力学计算题里的密度符号、应力符号本身就不适合纯文本保存等结构化阶段再处理。如果一页提取出来的文本顺序明显错乱试试把pdfplumber的layout参数去掉用默认模式重新提取。两种模式在文本排序算法上不一样对部分页面的结果差异很大哪个模式在当前页面输出更顺就用哪个。这一步不需要写复杂的规则多试两种参数比调一堆正则划算得多。3. 用正则把名词解释、简答题、计算题分开归档3.1 先看题型排版规律再写分类器把文本抽出来之后就要面对土力学题库里最常见的混排问题。名词解释一般是“1. 有效应力”简答题是“简述太沙基一维固结理论的基本假设”计算题则经常出现“已知某土样含水率w18%求孔隙比e”。这些句子特征非常明显用正则做规则分类比训练模型更可控。观察整套PDF里各种题型的写法建立一张特征对照表再按优先级逐条匹配。题型典型特征匹配关键词示例名词解释名词后紧跟冒号或破折号有效应力、孔隙比、灵敏度简答题以动词开头多为论述性简述、说明、论述、试述计算题含已知条件与求解要求已知、求、试算、计算选择题选项编号为A. B. C. D.A、B、C、D判断题内容简短题干带括号 、正误、是否正确匹配顺序上先把判断题和选择题抽走因为它们特征最明确再用“名词释义”的冒号模式处理名词解释剩下的文本块里按“简述”“试述”等动词判断简答题按“已知”“求”判断计算题。顺序很重要因为“简述某概念”也可能出现在名词解释段落里被前面规则截获后就再也不会走进简答题分支了。3.2 写一个按题型切分的Python函数import re def classify_question(text, idx): # 判断题题干短且带括号 if re.search(r[(]\s*[√×对错]\s*[)], text) and len(text) 60: return 判断题 # 选择题包含A. B. C. D.选项标记 if re.search(r[A-D][\.、], text) and re.search(r[A-D][\.、], text).group(): if len(re.findall(r[A-D][\.、], text)) 2: return 选择题 # 名词解释编号后跟术语术语后接冒号 m re.match(r(\d)[\.、]\s*([\u4e00-\u9fa5]{2,10})\s*[:], text) if m and len(text) 120: return 名词解释 # 简答题以动词开头 if re.match(r^(简述|说明|论述|试述|解释|分析|比较), text): return 简答题 # 计算题包含计算特征 if re.search(r已知|试算|计算|求[(]?\w, text): return 计算题 return 其他参数说明idx参数目前只是占位便于后续按原题顺序编号len(text) 60是判断题的特有约束因为名词解释也可能出现“对”或“错”的字样选择题分支判断了至少出现两个选项避免和简答题里的“A.方案”混淆。实际使用时分类器输出的“其他”类别值得留意它往往包含题目答案、解析、以及页眉页脚需要单独过滤掉。3.3 给土力学习题打上章节标签题型分完之后还不够一道土力学计算题是“地基沉降”章节还是“土压力”章节直接决定它能不能撑起一套模拟题。为此需要维护一个关键词表覆盖土力学课程最常见的章节概念。chapter_keywords { 土的物理性质: [含水率, 孔隙比, 饱和度, 重度, 密度, 土粒比重], 渗透与渗流: [渗透系数, 达西定律, 渗流力, 水力梯度, 流土, 管涌], 地基应力: [自重应力, 附加应力, 基底压力, 角点法, 应力分布], 压缩与沉降: [压缩系数, 压缩模量, 固结, 沉降量, 先期固结压力], 抗剪强度: [粘聚力, 内摩擦角, 莫尔圆, 库仑公式, 有效应力], 土压力: [主动土压力, 被动土压力, 静止土压力, 朗肯, 库仑], 边坡稳定: [安全系数, 滑裂面, 条分法, 边坡], 地基承载力: [临塑荷载, 极限承载力, 太沙基, 地基承载力特征值], }每个章节标签的匹配逻辑很简单如果题目文本里命中了某个关键词就给这道题打上对应的章节标签。一道题可能命中多个章节这是正常情况比如计算挡土墙后的土压力时会同时出现“粘聚力”和“主动土压力”。保留全部命中结果在抽题阶段再做权重处理。4. 生成模拟题把题库JSON化并按权重随机抽题4.1 设计题目结构方便后续扩展题目分类和打标完成后需要把结果统一序列化成JSON。这里的关键是保留足够多的字段而不是只存题干文本。一套土力学模拟题后续可能要导出成Word、Markdown、或者配合答题卡使用多存几个属性不会增加成本少了字段再补就麻烦了。{ id: T001, type: 名词解释, chapter: [有效应力原理], content: 有效应力, options: [], answer: 由土颗粒骨架传递的应力其值等于总应力减去孔隙水压力。, source_page: 17 }字段含义type记录题型chapter是章节标签数组options给选择题预留answer存放答案解析source_page标记这道题在原始PDF中的页码方便后续核对原文。id的编码规则最好带上题型前缀比如计算题用C001名词解释用N001这样后续出卷时能快速按前缀筛选。4.2 按章节权重抽题的随机算法抽题不能完全均匀随机因为土力学考试里“土的物理性质”和“地基沉降”通常是重点而“渗透与渗流”占比没那么大。常见做法是维护一个章节权重表抽题时先按权重选出章节再在对应章节里随机取题比直接在全库随机更能模拟真实考卷。import random import json with open(soil_questions.json, encodingutf-8) as f: questions json.load(f) weights { 土的物理性质: 5, 渗透与渗流: 3, 地基应力: 4, 压缩与沉降: 5, 抗剪强度: 4, 土压力: 3, 边坡稳定: 2, 地基承载力: 4, } def sample_exam(questions, weights, count20, seedNone): if seed is not None: random.seed(seed) pool_by_chapter {} for q in questions: for ch in q[chapter]: pool_by_chapter.setdefault(ch, []).append(q) chapters list(weights.keys()) chosen [] seen set() while len(chosen) count: ch random.choices(chapters, weightslist(weights.values()), k1)[0] q random.choice(pool_by_chapter[ch]) if q[id] not in seen: chosen.append(q) seen.add(q[id]) return chosen这里有个细节一道题可能同时属于多个章节如果直接计算总权重它被抽中的概率会比单章节题目高。seen集合保证了同一套卷子里不会出现重复题如果题库量大还可以改成同一题在同一套卷子里最多出现一次的前提下允许跨章节命中。seed参数用于复现抽题结果出AB卷时非常实用。4.3 导出成可打印的模拟卷抽完题之后最后一步是把题目按顺序渲染成Markdown或Word。逐个题型分组渲染比较符合考试习惯先放名词解释再放简答题计算题放最后。def render_exam(questions): lines [] order [名词解释, 选择题, 判断题, 简答题, 计算题] for t in order: qs [q for q in questions if q[type] t] if not qs: continue lines.append(f## {t}) for i, q in enumerate(qs, 1): lines.append(f{i}. {q[content]}) if q[options]: for opt in q[options]: lines.append(f {opt}) lines.append() lines.append() return \n.join(lines) with open(exam.md, w, encodingutf-8) as f: f.write(render_exam(sample_exam(questions, weights, count20, seed20240601)))order列表控制输出顺序题型名称和JSON里的type字段一一对应。输出时每道题之间保留空行方便手写答题如果想出带答案的教师版只需在渲染函数里同时判断一个show_answer开关。5. 用错题反馈反向补充题库的隐藏技巧5.1 把自测结果回填到题目JSON里抽题器能出卷但复习提分还得靠错题统计。我一般会在导出模拟卷的同时生成一个答题记录文件每道题记录“做对了还是做错了”“用时多少秒”“是否翻看了答案”。这个记录不需要做成Web服务一个CSV就够了列分别是题目ID、结果、耗时、备注。跑完几套模拟卷后汇总统计哪些题目的错误率超过一半把这些题目标记成high_yield: true下次抽题时给它们额外加权。5.2 用错误类型反查知识点标签土力学计算题的错法很集中要么是公式记混要么是参数代错。简单的做法是在题目的chapter标签之外再加一个error_type标签数组比如“把孔隙水压力当成有效应力”“固结度公式用错”。这些错误类型不需要预定义答题记录里备注什么就把它同步进JSON的对应字段。积累几轮之后这个题库就变成了针对个人弱点的专属复习资料比重新买一本习题集效率高得多。5.3 增量更新PDF时的幂等处理题库PDF经常更新可能是修订版增加了新题也可能只是换了封面。每次重新解析整个PDF再入库会发现之前记录的答题统计全部作废。要避免这个问题可以在JSON里记录来源文件的MD5和文件大小解析前先比对当前文件与记录是否一致。如果哈希变了只把新增的题目ID追加进题库旧题的答题记录原样保留。如果哈希相同但页码偏移了说明只是封面或前言变了直接沿用旧数据。这一步操作量不大但对长期维护题库的人来说能省下大量重复整理的时间。记住这个习惯解析PDF之前先把文件指纹算出来存好。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进