
本文介绍使用pymupdf(fitz)库从pdf中按行提取文本并关联页码与行号的实用方法,支持精准定位每行文本在文档中的物理位置,适用于内容分析、ocr后处理及可访问性增强等场景。
本文介绍使用pymupdf(fitz)库从pdf中按行提取文本并关联页码与行号的实用方法,支持精准定位每行文本在文档中的物理位置,适用于内容分析、ocr后处理及可访问性增强等场景。
在PDF文本提取任务中,仅获取纯文本往往不足以满足结构化分析需求——例如审计文档排版、构建带行号的可访问PDF阅读器、或对齐OCR识别结果与原始布局。虽然Apache PDFBox、iText和Aspose.PDF等Java库能实现页面级文本抽取,但它们默认不提供逐行坐标+逻辑行号的细粒度信息。而PyMuPDF(fitz)凭借其底层对PDF内容流与渲染模型的深度解析能力,成为实现“带行号文本提取”的高效选择。
核心原理在于:PyMuPDF的 page.get_text("blocks", sort=True) 方法将页面文本按视觉块(如段落)组织,每个块包含边界框(x0, y0, x1, y1)和内部文本字符串;再通过 str.splitlines() 拆分段落内换行,即可获得逻辑上的“行”。结合循环计数器,即可为每行分配唯一行号(从0起始,可按需调整)。
以下为完整示例代码:
import fitz # pip install PyMuPDF
doc = fitz.open("input.pdf")
for page in doc:
line_counter = 0
# 获取排序后的文本块(按从上到下、从左到右顺序)
blocks = page.get_text("blocks", sort=True)
for block in blocks:
# block[4] 是该块的文本内容(str),block[:4] 是 (x0, y0, x1, y1) 坐标
text_in_block = block[4]
lines = text_in_block.splitlines()
for line in lines:
# 输出:页码 + 当前全局行号 + 原始文本(去首尾空格)
print(f"Page {page.number}, Line {line_counter}: '{line.strip()}'")
line_counter += 1⚠️ 注意事项:
- 行号是逻辑行号(即程序遍历顺序),非PDF源文件中隐含的“行号”(PDF本身无行号概念);
- splitlines() 会按 \n, \r\n 等标准换行符切分,若PDF中存在软换行(未显式换行符但因宽度折行),PyMuPDF可能已将其合并为单行——此时需改用 page.get_text("dict") 获取更底层的字符级信息并基于y坐标聚类;
- sort=True 对保证阅读顺序至关重要,尤其在多栏或复杂版式PDF中;
- 中文/日文等CJK文本需确保字体嵌入完整,否则可能提取为空或乱码;建议搭配 page.get_text("text", flags=fitz.TEXT_PRESERVE_LIGATURES) 进行验证。
综上,PyMuPDF提供了兼顾简洁性与精度的行级文本提取方案。对于需要严格行定位的场景(如法律条文引用、代码PDF比对),建议进一步结合 block 的 y0/y1 坐标做行高归一化或跨块行合并处理,从而构建更鲁棒的行号映射体系。


















