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

使用fitz检测PDF布局:相邻文本块(含公式)被合并的解决咨询

解决fitz中普通文本与近间距公式的textblock拆分问题

针对你遇到的普通文本和独立公式因行间距小被识别为同一textblock的问题,确实可以通过细粒度坐标检测+特征区分+重新分组的方式解决,具体步骤如下:

  • 先获取页面的细粒度单词/字符数据
    用fitz的page.get_text("words")方法,能拿到每个单词的坐标(x0,y0,x1,y1)、文本内容、所属block/line编号等信息,这是拆分的基础。相比直接获取textblock,这个接口能让你拿到更底层的元素数据。

  • 区分普通文本与公式的特征
    公式和普通文本通常有明显特征差异,你可以从这几个维度判断:

    • 字体:公式常用专门的数学字体(比如Times New Roman Math、Latin Modern Math),普通文本多是常规宋体、Times New Roman等;
    • 字符集:公式包含大量数学符号(∑、∫、α等),可以用正则匹配这类特殊字符;
    • 垂直位置:公式的基线可能和普通文本不一致,比如行内公式可能居中对齐,而普通文本是基线对齐,对比同一行元素的y坐标范围能发现差异。
  • 按特征重新分组构建独立文本块
    遍历同一个原始textblock下的所有单词,根据上述特征把普通文本和公式分开,再按阅读顺序(从左到右、从上到下)重新组合成新的独立文本块。

示例代码片段

import fitz
import re

def split_textblock_with_formula(page):
    # 获取所有单词数据,按block_no分组
    words = page.get_text("words")
    block_groups = {}
    for word in words:
        x0, y0, x1, y1, text, block_no, line_no, word_no = word
        if block_no not in block_groups:
            block_groups[block_no] = []
        block_groups[block_no].append(word)
    
    split_blocks = []
    # 遍历每个原始block
    for block in block_groups.values():
        normal_text = []
        formula_text = []
        # 匹配数学符号的正则
        math_symbol_pattern = re.compile(r'[\u2100-\u214F\u2200-\u22FF\u2500-\u257F\u2600-\u26FF\u2700-\u27BF]')
        for word in block:
            x0, y0, x1, y1, text, _, _, _ = word
            # 检查是否包含数学符号,或者字体是否为数学字体
            font_info = page.get_fonts()[word[5]]  # 获取单词所属字体信息
            if math_symbol_pattern.search(text) or ("Math" in font_info[3] if len(font_info)>=4 else False):
                formula_text.append(text)
            else:
                normal_text.append(text)
        # 如果两个分组都有内容,就拆分成两个独立块
        if normal_text and formula_text:
            split_blocks.append(" ".join(normal_text))
            split_blocks.append(" ".join(formula_text))
        else:
            split_blocks.append(" ".join(normal_text + formula_text))
    return split_blocks

# 使用示例
doc = fitz.open("your_pdf_file.pdf")
page = doc[0]
result = split_textblock_with_formula(page)
for idx, block in enumerate(result):
    print(f"拆分后的文本块 {idx+1}: {block}")

关于坐标与阅读顺序的说明

你提到的检测单词坐标并按常规阅读顺序排序是必要的:

  • 坐标能帮你判断元素的上下左右位置关系,确保分组时不会把不同行的内容混在一起;
  • 阅读顺序排序(比如按y坐标从小到大,同一y范围内按x坐标从左到右)能保证拆分后的文本块内容逻辑和原PDF一致。

内容的提问来源于stack exchange,提问作者CAO RUI

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 15:35:46