You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PyMuPDF提取PDF文本时,文本提取顺序与视觉布局不符(坐标正确但逻辑顺序错误)

使用PyMuPDF提取PDF文本时,文本提取顺序与视觉布局不符(坐标正确但逻辑顺序错误)

我完全懂你碰到的这个糟心问题!复杂布局的PDF(比如多栏排版、混着表格的文档)经常会出现这种情况——PyMuPDF默认是跟着PDF内部的文本绘制顺序来提取内容的,但这个顺序和我们视觉上的阅读顺序往往完全不搭,哪怕每个文本块的坐标都是准确的。你之前试过的普通按x/y坐标排序之所以没起作用,是因为它太“一刀切”了,没考虑到多栏布局的栏边界,也没区分表格这类特殊元素的内部逻辑。

下面给你几个针对性的解决思路和实操方案:

核心思路:放弃默认顺序,基于坐标做精细化的文本块分组排序

既然PDF内部的文本顺序本身就有问题,我们就直接跳过它,把所有文本块拆成最小单元,然后模拟人类的阅读逻辑(先左栏后右栏,先上后下,表格按行/列顺序)来重新排序。

步骤1:获取结构化的文本块数据

先用PyMuPDF的page.get_text("dict")获取带坐标的结构化文本,而不是直接取纯文本。这个接口会返回每个文本块的边界框(bbox)、行、字符跨度等信息,方便我们后续处理:

import fitz  # PyMuPDF

doc = fitz.open("你的PDF文件路径.pdf")
page = doc[0]  # 取第一页示例
text_struct = page.get_text("dict")
# 过滤掉非文本块(比如图片、图形)
text_blocks = [block for block in text_struct["blocks"] if block["type"] == 0]

步骤2:针对多栏布局的排序方案

如果你的文档是多栏排版,首先要把文本块按“栏”分组,再在每栏内部按垂直顺序排序,最后按栏的顺序拼接:

def sort_multi_column_blocks(page, text_blocks):
    page_width = page.rect.width
    # 这里假设是两栏,可根据实际情况调整,也可以自动聚类x坐标来检测栏数
    column_gap = 50  # 栏之间的间距,可根据你的文档调整
    column_width = (page_width - column_gap) / 2
    
    # 按栏分组
    left_column = []
    right_column = []
    for block in text_blocks:
        bbox = block["bbox"]
        # 用文本块的中心x坐标判断属于哪一栏
        block_center_x = (bbox[0] + bbox[2]) / 2
        if block_center_x < column_width:
            left_column.append(block)
        else:
            right_column.append(block)
    
    # 排序规则:先按顶部y坐标(越靠上越先),再按左侧x坐标(越靠左越先)
    def block_sort_key(block):
        return (block["bbox"][1], block["bbox"][0])
    
    left_column.sort(key=block_sort_key)
    right_column.sort(key=block_sort_key)
    
    # 拼接文本:先左栏后右栏
    sorted_text = ""
    for block in left_column + right_column:
        for line in block["lines"]:
            for span in line["spans"]:
                sorted_text += span["text"] + " "
            sorted_text += "\n"
    return sorted_text

# 使用示例
sorted_result = sort_multi_column_blocks(page, text_blocks)
print(sorted_result)

步骤3:针对表格的特殊处理

如果文档里有表格,你可以先用PyMuPDF的page.find_tables()识别表格区域,然后单独对表格内的文本块按行/列排序:

def sort_table_blocks(table):
    # 从表格对象中提取单元格文本,按行优先排序
    sorted_table_text = ""
    for row in table.rows:
        row_text = "\t".join([cell.get_text().strip() for cell in row.cells])
        sorted_table_text += row_text + "\n"
    return sorted_table_text

# 识别页面中的表格
tables = page.find_tables()
for table in tables:
    table_text = sort_table_blocks(table)
    # 可以把表格文本替换到排序后的整体文本中,或者单独处理

额外小技巧

如果你不想自己写复杂的排序逻辑,也可以试试PyMuPDF的page.get_text("text", sort=True)参数,但这个参数只是简单按x/y坐标排序,对多栏、表格这类复杂布局的支持有限,还是自定义排序更靠谱。


备注:内容来源于stack exchange,提问作者Phalgun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 16:13:08