news 2026/9/17 13:59:44

从PDF到LaTeX:数学公式提取与知识库构建实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从PDF到LaTeX:数学公式提取与知识库构建实战

简介:这是一份面向考研学子的数学公式速查手册,专为应对研究生入学考试中的高等数学、线性代数、概率论等科目而整理,帮助考生解决公式繁多、易混淆、不会运用等痛点。资源包内为一份PDF电子文档,压缩包整体大小约3.16MB,便于在电脑、平板或手机上随开随查;目前在CSDN已有505人学习下载。手册依照考研数学知识体系编排,依次梳理基础概念、代数中的方程、不等式、矩阵与行列式、平面和空间几何、解析几何中的坐标系与向量、三角函数、微积分中的极限与微分、中值定理和泰勒公式,以及概率统计中的随机变量和统计量,并配有大量例题及答案。通过阅读和练习,考生不仅能系统记忆核心公式,还能熟悉典型题型的推导思路,提高解题速度与准确率。对数学基础薄弱或正在冲刺高分的考生来说,是一份实用且可反复查阅的备考资料。

1. 一份考研数学公式手册 PDF,暴露的是公式解析问题

一个工程师如果想把手头的《139高分系列—考研数学公式手册.pdf》变成自己真正用得上的知识库——能全文搜索、能随机抽背、能按章节自动出题——第一个拦路虎往往不是数学知识,而是 PDF 本身的格式。数学公式在 PDF 里并不是以“可复制的文本”存在的,它可能是一段被压缩过的字体子集、一组矢量绘图指令,甚至一整张高分辨率位图。直接复制粘贴的结果通常是乱码,或者把积分号、分式、上下标丢得干干净净,只剩下一串断断续续的普通字符。

整个处理链路分四步:先判断文档里公式的存储形态,再用 Python 把文本公式和图形公式分别抽出来,接着转成统一的 LaTeX 表示,最后存入本地数据库并导出成能检索的笔记卡片。这套方案适合想把纸质或 PDF 数学资料数字化、结构化的一线工程师,也适用于任何需要批量处理公式类文档的场景。下面所有操作全部使用可离线运行的开源工具,不依赖特定在线服务,处理过程中每一步都可以自己控制输出结果。

2. PDF 里数学公式的存储方式与解析原理

2.1 公式不是文本:字体、Glyph 与编码表

PDF 里一段“看起来是公式”的内容,本质上是一串字符代码与字体渲染指令的组合。每个字符代码对应字体文件里的一个字形 Glyph,而 Glyph 的形状由贝塞尔曲线描述。公式手册这类排版文档通常使用嵌入子集后的数学字体,字体文件只包含文档里出现过的字形,字符代码的编码空间不一定按照 ASCII 或 Unicode 排序。

判断能不能直接从文本层取公式,关键看 PDF 是否带 ToUnicode CMap 映射表。这张表负责把字体内部的字符代码映射回 Unicode 码点,没有它,解析器拿到的就是一组无法解释的数字,公式复制出来自然是乱码。处理前先确认文档的来源:排版软件导出的 PDF 通常带完整的 ToUnicode 映射,而扫描后加 OCR 生成的文档则根本没有文本层,只能走图形识别路线。这个判断决定了后续工具的选择,方向搞反会浪费大量时间在无谓的文本抽取上。

拿到一份公式手册 PDF,我一般先检查前几页的字体列表和编码方式。用 PyMuPDF 的page.get_fonts()可以快速看出文档用了哪些字体、是否为嵌入子集、有没有对应的 Unicode 映射,一分钟内就能判断后续走哪条解析路线。

2.1.1 快速检查字体的命令
import fitz doc = fitz.open("139高分系列—考研数学公式手册.pdf") for page_no in range(min(3, len(doc))): page = doc[page_no] for f in page.get_fonts(): xref, ext, ftype, basename, refname, encoding = f print(f"page={page_no} type={ftype} base={basename} encoding={encoding}")

这段代码输出每页用到的字体名称、字体类型(Type1TrueTypeType3等)以及编码方式。Type3 字体通常是文档自定义的一组绘图指令,常见于老式数学排版系统生成的文件,这类页面基本无法通过文本层还原公式,必须做图形识别。看到 Type3 就不要在文本抽取上继续纠结,直接切到公式 OCR 路线。

提示:如果整页都是扫描图像,page.get_fonts()返回空列表,此时不要浪费时间做文本层解析,直接用公式 OCR 处理整页截图。

2.2 识别 PDF 里公式区域的三种信号

数学公式在 PDF 中可能以三种形态出现,工具选择完全取决于遇到的是哪一种。

第一种是文本运算符承载的公式。PDF 内容流里会出现TjTJTdT*等操作符,公式由文本对象组成,可以用 PyMuPDF 的page.get_text("rawdict")拿到每个字符的位置、字号和旋转角度,再按数学排版习惯重排。第二种是矢量图形公式。内容流里出现大量mlcf路径操作符,分式线、根号、积分号主体往往是用路径画的,这类公式要把路径包围盒与附近的文本块做空间匹配才能恢复结构。第三种是图像公式,整段公式被渲染成位图放进页面,没有文本信息,只能交给公式识别模型。

公式形态PDF 内容流特征推荐处理方式适合工具
文本公式Tj / TJ / Td 操作符文本抽取 + 布局重排PyMuPDF、pdfplumber
矢量公式m / l / c / f 路径操作符路径包围盒 + 语义合并PyMuPDF + 自定义算法
位图公式XObject 图像对象公式 OCRPix2Text、Mathpix

区分这三种形态并不难,用 PyMuPDF 读取页面内容流,统计文本运算符与路径运算符的数量。文本运算符数量明显多于路径运算符的页面,公式大概率以文本为主;反之则多为矢量绘制;如果页面对象里只有Image对象,那基本就是纯位图。实际操作中,一份排版良好的公式手册往往是混合形态:普通文字是文本,根号与分式线是矢量,个别复杂的矩阵可能被做成图片,需要按区域分别处理。

2.3 抽取策略选型:先文本、后图形、最后 OCR

针对公式手册,我建议的抽取顺序是固定的:第一步用文本层抽取,把能拿到的字符连同坐标保存下来;第二步对文本层缺失的公式区域做图像截取,交给公式识别模型;第三步把两路结果合并,按页面坐标做位置对齐,去重后统一输出。这样做的原因是文本抽取速度快、准确率高,而公式 OCR 每页耗时在秒级,能省则省。

选型时还要看手册的版式。如果是单栏、公式独立成行的文档,直接按(x, y)坐标排序即可恢复阅读顺序;如果是双栏混排,需要先做栏切分。判断栏数可以统计页面文字的 x 坐标分布,把出现两个明显聚集区间的页面标记为双栏处理。这步看起来不起眼,但漏掉会导致公式跨栏拼接,后面 LaTeX 渲染出来的内容完全不可读。

3. 用 Python 抽取考研数学公式并转成 LaTeX 的可执行方案

3.1 最小环境与文本公式抽取

准备一个 Python 3.10 以上的环境,安装 PyMuPDF、Pix2Text 和 Pillow。选择 PyMuPDF 而不是 pdfplumber,是因为它在坐标获取和截图渲染之间切换成本最低,同一个fitz.Page对象既能拿文本块坐标,又能直接栅格化输出公式图片,省去在两个库之间反复换算页面坐标系的工作。

pip install pymupdf pix2text pillow

下面这段代码做第一轮抽取:把 PDF 每页的文本块按位置排序后输出,同时把内容写入 JSON 行文件,保留坐标信息,方便后续与 OCR 结果对齐。

import fitz import json doc = fitz.open("139高分系列—考研数学公式手册.pdf") out = open("text_layer.jsonl", "w", encoding="utf-8") for pno in range(len(doc)): page = doc[pno] blocks = page.get_text("dict")["blocks"] for b in blocks: if b["type"] != 0: # 只保留文本块, 忽略图像块 continue for line in b.get("lines", []): text = "".join( span["text"] for span in line["spans"] if span["text"].strip() ) if not text: continue x0, y0, x1, y1 = line["bbox"] rec = { "page": pno + 1, "x0": round(x0, 1), "y0": round(y0, 1), "x1": round(x1, 1), "y1": round(y1, 1), "text": text, } out.write(json.dumps(rec, ensure_ascii=False) + "\n")

按行输出是为了尽量保留公式中上下标同处一行的布局,虽然这会丢失部分垂直结构,但比按块混杂文字要好得多。如果后续需要更细的字符级信息,把page.get_text("dict")换成page.get_text("rawdict")即可,代价是数据量增加一个数量级,处理速度会明显下降。坐标保留四位小数足够,过多位数对后续对齐没有帮助,反而让 JSON 膨胀。

3.2 对图形公式做 OCR 并输出 LaTeX

文本层抽完之后,处理那些文本层缺失或本身就是图片的公式。先用 PyMuPDF 按公式区域裁剪截图,再交给 Pix2Text 识别。识别结果默认是 LaTeX 字符串,正好作为后续知识库的存储格式。

from pix2text import Pix2Text p2t = Pix2Text.from_config( enable_formula=True, enable_text=False, formula_config={"language": "en", "use_doc_orientation_sort": False}, ) def ocr_formula(page, clip, index): pix = page.get_pixmap(clip=clip, dpi=300) pix.save(f"formula_{index}.png") result = p2t.recognize(f"formula_{index}.png") return result

这里的dpi=300是识别准确率的关键参数。过低会丢失小字号上下标的细节,过高会引入抗锯齿噪点且处理时间翻倍。enable_text=False让模型只输出公式部分,避免把旁边的中文注释混入 LaTeX 结果。use_doc_orientation_sort=False关闭自动版面排序,因为我们已经通过clip指定了裁剪区域,不需要模型再做整页版面分析,能省掉一部分耗时。

Pix2Text 里还有几个参数直接决定输出质量,列成一张常用参数表:

参数作用推荐值调整方向
dpi截图渲染清晰度300公式空隙大时可降到 200 提速
enable_formula是否启用公式识别模型True纯文本页关掉可省约 40% 耗时
use_doc_orientation_sort是否让模型自动排版面False整页截图时建议改为True

注意 Pix2Text 识别返回的结构是一个列表,每个元素包含typetext字段。实际使用时要过滤typeformula的条目,避免把中文文本识别结果混入公式库。识别结果里的 LaTeX 通常带有$$...$$包裹层,入库前可以把外层的美元符号去掉,只保留内部内容,方便与其他文本里的公式拼接。

3.3 用 latexmk 验证 LaTeX 可编译

OCR 出来的 LaTeX 字符串并不保证可编译,常见问题包括缺\right、花括号不配对、宏包名称拼错。我的做法是把每条公式放进一个最小文档里,用 latexmk 批量编译,编译失败的条目打回人工核查。这个过程机械但能拦住大部分脏数据。先把 OCR 输出里的外层$$剥掉,再填入文档模板:

sed 's/^\$\$//; s/\$\$$//' formula_raw.txt > formula_clean.txt
% check_formula.tex \documentclass{article} \usepackage{amsmath, amssymb} \pagestyle{empty} \begin{document} \thispagestyle{empty} $\displaystyle \frac{\partial u}{\partial t} = a^2 \left( \frac{\partial^2 u}{\partial x^2} + \frac{\partial^2 u}{\partial y^2} \right) $ \end{document}

编译命令:

latexmk -pdf -interaction=nonstopmode -halt-on-error check_formula.tex

-halt-on-error是为了让编译在第一个错误处停下,避免错误信息被大量重复日志淹没;-interaction=nonstopmode禁止编译器向终端询问交互输入,保证批量执行时不会挂起等待。公式量大时,建议把每条公式编号放进独立目录并行编译,用xargs -P 4控制并发数,不要一个 latexmk 进程跑到底。

4. 把公式手册变成可检索的本地知识库

4.1 统一存储:LaTeX 在 Markdown 里的两种渲染差异

公式抽取只是第一步,最终要落成一个能查、能背、能复用的知识库。我选择 Markdown 作为容器,用$...$表示行内公式,用$$...$$表示独立公式。但在实际渲染时,必须区分 KaTeX 与 MathJax 的差异。KaTeX 响应快、适合本地笔记软件,但宏包支持不全;MathJax 兼容性好,但渲染稍慢。公式手册里高频出现的语法在两种引擎下的表现并不一致,提前确认能避免笔记导入后大面积公式显示异常。

LaTeX 结构KaTeX 支持MathJax 支持备注
\frac{a}{b}支持支持无差异
\begin{bmatrix}...\end{bmatrix}支持支持注意&需要转义
\substack需配置支持KaTeX 需 0.16 以上版本
\cancel{}需扩展默认支持Obsidian 中需配置一次
\overbrace{}支持支持显示效果依赖字体

对于公式手册这种以符号和结构为主的文档,KaTeX 的覆盖面已经足够,不需要为了个别宏包全面切到 MathJax。真正需要注意的是导出的 Markdown 里,反斜杠和花括号会被某些文本处理器当作转义字符处理,写入文件前最好用原始字符串保存,避免\frac变成frac。我在导出脚本里统一用repr(latex)检查一遍转义结果,能拦截掉大部分这类低级错误。

4.2 建公式索引表并用 SQL 查询定位

公式手册的价值在于快速定位。把每条公式连同它的标题、章节、来源页码、原始 LaTeX 存入 SQLite 表,之后任何检索都能用 SQL 完成。选择 SQLite 而不是直接维护 JSON 文件,是因为数据量到几千条后,JSON 全量扫描的延迟会变得明显,而 SQLite 的 B-tree 索引能让LIKE检索稳定在毫秒级,还不需要额外启动服务进程。

CREATE TABLE formula( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, chapter TEXT, latex TEXT NOT NULL, page INTEGER, source TEXT, created_at TEXT DEFAULT (datetime('now')) ); CREATE INDEX idx_formula_title ON formula(title); CREATE INDEX idx_formula_page ON formula(page);

查询示例:

SELECT id, title, page, latex FROM formula WHERE title LIKE '%三重积分%' OR latex LIKE '%iiint%' ORDER BY page;

LIKE '%iiint%'直接搜 LaTeX 代码并不可靠,因为同一个公式在不同 OCR 输出里可能是\int\int\int而非\iiint。更稳妥的做法是再维护一张同义词表,把 LaTeX 变体、中文标题、常用符号名关联到同一个 formula id。查询时先通过同义词表展开再搜索,比如“三重积分”同时映射到\iiint\int\int\int,这样无论用户按中文名还是按符号查,都能命中同一条记录。

4.3 导出 Anki 卡片与 Obsidian 笔记

公式库建好后,导出成 Anki 卡片来背诵是自然需求。Anki 的apkg格式解析复杂,但可以通过生成 CSV 再导入来避开二进制格式。CSV 第一列是题目,第二列是答案,答案保留 LaTeX 原文,配合 Anki 的 MathJax 支持即可正常渲染。

import csv import sqlite3 conn = sqlite3.connect("formula.db") rows = conn.execute( "SELECT title, latex FROM formula WHERE chapter='高等数学' LIMIT 200" ).fetchall() with open("anki_math.csv", "w", newline="", encoding="utf-8") as f: w = csv.writer(f) w.writerow(["front", "back"]) for title, latex in rows: # Anki 支持用 \(...\) 渲染行内公式 w.writerow([title, f"\\({latex}\\)"])

写给 Obsidian 的部分同样是 Markdown,只是额外在 YAML front matter 里写入标签与页码索引,方便后续用 Dataview 做属性查询。导出路径建议按章节划分目录,例如高等数学/多元微分.md。这样即使仓库里文件数量增长到几百个,Obsidian 的文件索引也不会因为单目录文件过多而变慢。

5. 验证考研数学公式正确性的方法与进阶技巧

5.1 文本级校验:扫描变量一致性

公式转成 LaTeX 后最容易犯的错误是字母识别混淆,比如把x识别成z,把α识别成a。用 LaTeX 编译只能保证语法正确,无法保证语义正确,所以我最后一道工序是文本级校验:把整本手册的所有公式拼成一个纯文本文件,提取其中出现过的全部标识符,检查同一个名字有没有被赋予两种不同的含义。

实操上可以写一段正则把\alpha\betaaf这类符号抽取出来,按章节统计出现频率。某个符号在全书出现次数超过阈值,却在某一页突然没有定义就出现,就要警惕识别错误。这种启发式方法不能替代人工校对,但能把错误范围从几百处缩小到几十处,之后人工复核的工作量会大幅下降。

5.2 渲染级回归:对比截图的像素差异

如果原 PDF 里的公式是清晰的位图,可以用渲染对比做自动回归。把原图截出来,同时把 LaTeX 渲染成同样尺寸的图片,计算两者结构相似度,差异过大的条目自动进入待审核列表。先安装图像对比依赖:

pip install opencv-python scikit-image
from skimage.metrics import structural_similarity as ssim import cv2 orig = cv2.imread("clip_137.png", cv2.IMREAD_GRAYSCALE) rendered = cv2.imread("render_137.png", cv2.IMREAD_GRAYSCALE) # 统一尺寸后计算结构相似度 orig = cv2.resize(orig, (480, 160)) rendered = cv2.resize(rendered, (480, 160)) score = ssim(orig, rendered) print(f"page=137 ssim={score:.4f}")

SSIM 大于 0.9 的条目直接通过,0.75 到 0.9 之间的进入抽查队列,低于 0.75 的强制人工核对。

注意:SSIM 对整体亮度敏感,对比前务必统一背景色与位深,否则得分会被系统性拉低,误报率会非常高。背景统一用纯白,字体颜色用纯黑,避免抗锯齿带来的偏差。

5.3 最后一招:对高价值章节做双向推导校验

对于高等数学里三重积分、曲线曲面积分这类重点章节,我还会多花一步:把公式前后的文字说明也抽出来,按编号配对。公式手册里的定理类公式往往有成对结构,例如先给出计算式,再列出使用条件。如果从手册里抽出的 LaTeX 中找不到对应的条件表达式,说明该页的解析可能漏掉了部分区域。这时回头检查该区域的图像切分边界,把裁剪矩形的边向外扩展 2 到 3 个像素,再重新识别一遍,就能找回大部分漏掉的上下标。

本文还有配套的精品资源,点击获取

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

Ubuntu下无root导出微信聊天记录:SQLCipher解密与CSV分析

1. 这不是“破解”,而是一场标准的数据主权实践你有没有过这样的时刻:换新手机前夜,盯着微信里几千条聊天记录发呆——那些和家人确认年夜饭菜单的语音、和同事敲定项目节点的文字、甚至自己随手发的备忘录图片,全被锁在一台设备里…

作者头像 李华
网站建设 2026/9/17 13:58:23

Cursor 的 @Codebase 还在胡诌 jQuery 方案?TaoToken 这样改 Base URL

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 13:57:15

自动售货机PLC控制系统设计:可靠性、I/O映射与梯形图时序控制

简介:本资源是一份面向自动化、电气工程及相关专业初学者与课程设计学生的PLC控制系统实践文档,聚焦基于西门子S7-200系列PLC的自动售货机整套设计方案,解决从控制逻辑建模到硬件落地的关键问题。文档完整覆盖系统设计原理、I/O点分配、顺序功…

作者头像 李华
网站建设 2026/9/17 13:56:01

AI-ISP不是升级,而是图像处理范式的重构

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 13:54:27

InternVL S3对象存储训练指南:大规模数据的云端读取完整方案

InternVL S3对象存储训练指南:大规模数据的云端读取完整方案 【免费下载链接】InternVL [CVPR 2024 Oral] InternVL Family: A Pioneering Open-Source Alternative to GPT-4o. 接近GPT-4o表现的开源多模态对话模型 项目地址: https://gitcode.com/GitHub_Trendin…

作者头像 李华