尧图精选

PDF教材解析实战:用Python提取文本、还原大纲并生成题库

🕒 发布时间:2026/9/19 15:08:13 📁 来源:尧图网络
简介面向初学者的计算机基础知识入门PDF系统梳理了计算机概述、系统组成、PC硬件系统、数据在计算机中的存储以及多媒体技术等核心章节适合正在学习计算机原理或准备计算机等级考试的初中级读者。资源为单个PDF文档压缩包大小11.14MB便于在手机或电脑上直接阅读既可作为课堂讲义也能用于考前回顾重要概念。已有50人下载学习。内容不仅涵盖计算机发展历程与分类、应用领域还详细介绍了冯·诺依曼结构、CPU与总线、内外存储器、输入输出设备等硬件构成并解释了二进制、数制转换、字符编码和内存容量等存储概念同时涉及文件管理、开关机操作和计算机病毒预防等实操性知识可以帮助读者从基础概念到实际使用建立完整的计算机知识框架。1. 为什么要把一份计算机基础PDF“拆”成结构化数据很多工程师拿到教材PDF的第一反应是复制粘贴但《计算机概述-计算机基础知识.pdf》这类讲义往往目录和正文混排页眉里还带着“cai.”平台水印直接复制出来的文本是碎的。这份PDF核心内容包括计算机发展史、冯·诺依曼结构、总线、RAM/ROM、多媒体技术等覆盖了计算机基础知识的全部骨架但它的排版结构并不适合直接阅读或检索。我把它当作一个典型的数据源记录从PDF文本提取、章节树还原到考点题库生成的完整处理链路。适合需要在批量教材上做知识库、题库系统或在线课程的开发者。2. PDF解析的第一课用pdfplumber摸清文本层2.1 为什么先选pdfplumber处理中文PDF时选库的第一标准不是速度快而是文本顺序和坐标还原是否可靠。pdfplumber基于pdfminer.sixextract_text()会按页返回带布局顺序的字符串对中文教材的段落换行和全角标点处理比PyPDF2稳定得多。PyPDF2更擅长页面级操作比如拆分合并它的文本提取经常把中文按字体片段切碎PyMuPDFfitz性能好但get_text()返回的文本块顺序在某些排版下会跳行需要额外排序。所以我通常先用pdfplumber做一次“体检”确认这份PDF到底有没有文本层、页眉水印出现在哪些位置。2.2 提取页面文本的基准代码拿到PDF后的第一件事是看页数和前几页的文本质量。下面这段代码可以在几分钟内给出结论import pdfplumber pdf_path 计算机概述-计算机基础知识.pdf with pdfplumber.open(pdf_path) as pdf: total len(pdf.pages) print(总页数:, total) for page_no in [0, 1, 2, 10]: page pdf.pages[page_no] text page.extract_text() if text: print(f--- 第 {page_no 1} 页 ---) print(text[:400]) else: print(f第 {page_no 1} 页没有文本层需要 OCR)这段代码里pdfplumber.open()接收文件路径并返回Pdf对象page.extract_text()默认使用pdfminer的布局分析按阅读顺序拼接文本。需要注意x_tolerance参数它控制同一行内相邻字符的合并间距默认是3。如果PDF里中文被拆成“计 算 机”这种单字加空格的形式可以把x_tolerance调到5甚至8字符会被更积极地合并成完整词。反之如果文本被错误粘连就调小这个值。除了文本页面的尺寸、页边距也可以通过page.width、page.height拿到。对于判断后续是否需要ocr这一步很关键。2.3 表格和页面结构怎么拿计算机基础知识的PDF里“1.2.2 总线结构”这类页面经常有地址总线、数据总线、控制总线的对比表格。pdfplumber的extract_tables()能把表格直接解析成二维列表省去手写坐标截取。with pdfplumber.open(pdf_path) as pdf: page pdf.pages[12] # 假设第13页是总线结构 tables page.extract_tables() for table in tables: for row in table: cells [c.replace(\n, ) if c else for c in row] print(cells)extract_tables()返回的是list[list[list]]结构最外层是页内多个表格第二层是行第三层是单元格。单元格里的换行符通常需要清理否则后续做文本分析时会把表格内容拆散。这个方法对有线框的表格准确率很高但对无线框表格可能返回空列表。遇到这种情况我会退回extract_text()用正则从文本里抽取关键字段。下面这个表是我在多个PDF工具里实际对比后的选择供初期选型参考工具文本提取表格提取中文兼容适用场景pdfplumber好好较好排版规整的教材PDFPyMuPDF (fitz)好中中大批量快速处理PyPDF2差无差页面级操作Camelot依赖好中复杂表格专项解析如果extract_text()在某一页返回None说明这一页是纯扫描图没有文本层。这份PDF大部分页面有文本层只有个别页的目录乱码所以暂时不需要OCR。若你真遇到扫描版建议用ocrmypdf先做一层OCR再回来走这套流程而不是直接上深度学习模型。3. 标题层级与中文乱码从PDF到干净的Markdown大纲3.1 中文乱码和噪声字符的清理PDF提取出的文本并不等于书上的文字。页眉“cai.”是教学平台的标识它和“1.1 计算机概述”出现在同一行目录页还有全角空格、版权符和重复的页码。直接拿这些文本去建知识库目录和正文会混在一起。我的处理分两步先按行切割再用正则把噪声字符替换掉。import fitz # PyMuPDF doc fitz.open(计算机概述-计算机基础知识.pdf) lines [] for page_no in range(len(doc)): page doc[page_no] text page.get_text(text, sortTrue) for raw_line in text.split(\n): # 清理平台水印和多余空格 clean raw_line.replace(cai., ).strip() clean re.sub(r\s, , clean) if clean: lines.append((page_no 1, clean)) print(lines[:20])这里用sortTrue让文本块按阅读顺序输出避免跨页内容跳位。.replace(cai., )只对特定水印有效如果你的PDF页眉是其他字符可以改成re.sub(r[a-z]{2,3}\., , raw_line)但小心别把章节编号后面的点也删掉。清理后的lines列表保留页码和文本后面生成大纲时能直接定位到页。3.2 用正则把“1.1.1”变成大纲教材里的标题格式很统一一级是“1”二级是“1.1”三级是“1.1.1”后面跟中文标题。用正则^\d(\.\d)*\s*[\u4e00-\u9fff]可以匹配这种结构。注意原PDF里“1 . 1 计 算 机 概 述”这种中间带空格的变体需要先去掉空格再匹配。import re def heading_level(clean_line): # 匹配 1、1.1、1.1.1 这类编号 m re.match(r^(\d(?:\.\d)*)[\.\s](.)$, clean_line) if not m: return None, None, None numbering, title m.group(1), m.group(2).strip() level numbering.count(.) 1 return level, numbering, title markdown_lines [] for page_no, line in lines: level, numbering, title heading_level(line) if level is None: continue # 一级标题用 ##二级用 ###三级用 #### markdown_lines.append(f{# * (level 1)} {numbering} {title} (p.{page_no})) print(\n.join(markdown_lines[:15]))heading_level()返回三个值标题层级、编号、中文标题。层级由编号中点的个数决定“1”是level 1“1.1”是level 2。转换成Markdown时level 1个#是因为在最终的文档系统里页面顶级标题已经占了#所以章节从##开始。每行后面的(p.页码)是溯源信息后面做题库引用出处时很有用。这里有个坑目录页的“1.1 计算机概述”和正文里的“1.1 计算机概述”会同时被匹配生成重复标题。我一般会丢弃PDF前两页目录页或者用编号重复检测如果同一编号在后续页面再次出现保留第一次后续的当作正文跳过。3.3 验证目录树是否完整生成大纲后不能直接相信正则。原PDF有一个“返回本章”的跳转机制正文里可能夹杂“1 . 1 . 1计 算 机 的 发 展 概^况”这种带脱字符的标题正则匹配会失败。所以我会把生成的大纲和教材的“教学目标和要求”进行对照检查层级是否连续。下表是从样例PDF中提取的一部分标题和原始章节结构的对照结果提取标题预期层级实际生成层级页码1 计算机基础知识一级## 111.1 计算机概述二级### 1.111.1.1 计算机的发展概况三级#### 1.1.111.2 计算机系统组成二级### 1.251.2.2 总线结构三级#### 1.2.27检查时重点看编号是否跳跃比如出现“1.1.1”后直接跳到“1.1.3”说明“1.1.2”可能被正则漏掉了。这种情况我会单独打印出该页的原始文本手动补上标题。对于这份PDF漏网的主要是带^符号的标题清理时把^去掉即可。4. 从计算机基础知识里抽取考点规则命中与题库初稿4.1 先圈定考点关键词教材内容有限考点也相对固定。我从原始PDF里抽取的高频知识点包括冯·诺依曼、存储程序、RAM、ROM、地址总线、数据总线、控制总线、巨型机、微型机、多媒体。把这些关键词做成一个列表逐行扫描已经清洗过的文本。命中关键词的行并不都是可用的题目素材比如目录行“1.1.1 计算机的发展概况”里不包含这些词但“总线的种类”这一节下面会有很多句子。所以还需要做一次短语过滤。keywords [冯·诺依曼, RAM, ROM, 地址总线, 数据总线, 控制总线, 巨型机, 多媒体] blacklist [返回本章, 返回本节, 教学目标, 电子器件] candidates [] for page_no, line in lines: if len(line) 15: continue if any(b in line for b in blacklist): continue for kw in keywords: if kw in line: candidates.append({page: page_no, keyword: kw, sentence: line}) break print(len(candidates))这里len(line) 15过滤掉短标题blacklist过滤掉导航文字。关键词匹配用的是in不是全等所以“RAM”能命中“随机存储器RAM”这种带前后缀的句子。一个句子可能包含多个关键词用break避免重复计数。4.2 生成填空和判断题有了候选句子就可以生成基础题型。填空题只需要把关键词替换成____判断题则需要依赖句子里的判断词比如“由...组成”“是...”“不能...”等。下面这段代码同时生成两种题import json fill_blanks [] true_false [] judge_patterns [由, 是, 不能, 可以, 属于] for item in candidates: kw item[keyword] sentence item[sentence] # 填空题关键词替换为下划线 if sentence.count(kw) 1: fill sentence.replace(kw, ____) fill_blanks.append({type: fill, page: item[page], question: fill, answer: kw}) # 判断题有判断词且句子长度适中 if len(sentence) 25 and any(p in sentence for p in judge_patterns): statement sentence.replace(kw, f[{kw}], 1) true_false.append({type: judge, page: item[page], statement: statement, answer: 对}) print(json.dumps(fill_blanks[:2], ensure_asciiFalse, indent2))填空题里如果关键词在一句话中出现多次replace会全替换导致答案不确定所以count(kw) 1这个条件很有用。判断题不做替换而是把关键词用[ ]括起来这样学生在刷题时能看到原文表述判断是否合理。answer字段目前全部置为“对”这是为了初筛更严谨的做法是人工校准或者根据句子是否含“不能”“不可以”把答案反转为“错”。抽取结果示例页码类型题干答案1填空世界上第一台电子数值积分计算机诞生于____年。19463填空____是计算机中最关键的部件。CPU7判断地址总线是单向的其位数决定了CPU的寻址能力。对这里第3行的判断句子关键词“地址总线”后面跟“是单向的”我们的简单规则无法判断正误只知道它来自教材正文。要更准确需要引入否定词表。常见做法是如果句子包含“不能”“不可以”“无法”就把答案置为“错”。但这会让“断电后信息不会丢失”这类双重否定句判断错误所以我把这个规则只作为初筛导出后再人工过一遍。4.3 导出成JSON方便接在线刷题题库最终要交给前端或APPJSON是通用格式。把fill_blanks和true_false合并成一个列表写入文件question_bank fill_blanks true_false with open(computer_basics_questions.json, w, encodingutf-8) as f: json.dump(question_bank, f, ensure_asciiFalse, indent2)ensure_asciiFalse确保中文直接以UTF-8保存而不是\u转义序列。indent2让文件可读性更好方便在编辑器里手动修改答案。如果你的系统需要对接现有题库平台可以再把这个JSON转换成CSV在Excel里批量修改“answer”字段。规则抽取的题面质量大约覆盖六成考点剩余四成需要人工补充这属于正常情况。5. 教材PDF进阶操作转Word、网页打印与拆分编辑5.1 pdf2docx处理中文教材PDF要把这份《计算机概述-计算机基础知识.pdf》变成可编辑的Word文档最有用的工具是pdf2docx库它基于PyMuPDF和python-docx能保留大部分中文排版。安装后一行代码完成转换from pdf2docx import Converter cv Converter(计算机概述-计算机基础知识.pdf) cv.convert(computer_basics.docx) cv.close()转换过程中会输出每个页面的进度。需要注意pdf2docx对带复杂表格的页面转换效果一般比如“总线结构”那页的三栏表格可能会变成纯文本。如果追求版式还原建议用Adobe Acrobat的导出功能但开源方案够用。转换后的Word里仍然包含“cai.”页眉需要再用Word的查找替换功能批量清理。5.2 用Chrome打印把Markdown变成PDF处理完大纲和题库后如果想生成一份干净的讲义PDF不需要再依赖原始PDF。把Markdown转成HTML再用Chrome的无头模式打印即可。Chrome的打印引擎对中文支持很好字体渲染清晰。# 先把Markdown转HTML再调用Chrome headless打印 pandoc computer_basics.md -o computer_basics.html chrome --headless --disable-gpu --print-to-pdfcomputer_basics.pdf computer_basics.html--headless让Chrome在后台运行--disable-gpu避免部分Linux服务器上的渲染问题--print-to-pdf指定输出路径。这个方案比在浏览器里手动按CtrlP更适合批量生成。如果连pandoc都不想装也可以在VS Code里装Markdown PDF插件直接在编辑器右键导出但自定义页眉页脚会麻烦一点。5.3 qpdf做页面拆分与合并教材PDF按章节拆分是高频需求。比如第一章“计算机基础知识”占了前10页想单独拿出来发给同事用qpdf命令行最直接# 拆出第1到10页 qpdf --empty --pages 计算机概述-计算机基础知识.pdf 1-10 -- chapter1.pdf # 把两个PDF按顺序合并 qpdf --empty --pages a.pdf 1-z b.pdf 1-z -- merged.pdf--empty表示从一个空PDF开始--pages后面跟输入文件名和页码范围1-z表示所有页最后是输出文件名。这套命令不依赖Python环境适合在脚本里调用。如果你用的是搜狗PDF编辑器这类带图形界面的工具也可以直接拖选页面拆分但qpdf在批量处理时更稳定。多个PDF合并时注意目录页码和实际页码的偏差通常先拆分再合并能减少乱序问题。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →