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

如何使用pdfminer.six提取指定PDF文本并保留原有布局?

如何用pdfminer.six提取PDF时保留原有布局?

嘿,我来帮你搞定这个问题!你现在用的TextConverter确实只会输出纯文本,完全丢掉了原PDF的布局结构——要实现保留布局的文本提取,得换个思路:直接解析PDF的布局元素,然后根据它们的位置信息来重新排版。

核心思路

PDF里的文本都是以带位置信息的元素(文本块、文本行、单个字符)存在的,我们可以用PDFPageAggregator来获取这些元素的坐标,然后按原页面的上下左右顺序排列文本,再用空格模拟缩进和分栏,还原大致布局。

完整代码示例

首先导入需要的模块:

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfpage import PDFPage
from pdfminer.layout import LAParams, LTTextBox, LTTextLine
from pdfminer.converter import PDFPageAggregator

然后定义提取函数:

def convert_pdf_to_layout_txt(path):
    # 初始化资源管理器和布局参数
    rsrcmgr = PDFResourceManager()
    laparams = LAParams()
    # 可根据PDF调整这些参数优化识别效果
    laparams.line_overlap = 0.5
    laparams.word_margin = 0.1
    
    # 创建布局聚合器,用于解析页面布局
    device = PDFPageAggregator(rsrcmgr, laparams=laparams)
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    
    full_text = []

    with open(path, 'rb') as pdf_file:
        for page in PDFPage.get_pages(pdf_file, check_extractable=True):
            interpreter.process_page(page)
            # 获取当前页面的布局对象
            layout = device.get_result()
            
            # 收集所有带位置的文本行
            text_lines = []
            for obj in layout:
                # 遍历文本块和文本行元素
                if isinstance(obj, (LTTextBox, LTTextLine)):
                    for line in obj:
                        if isinstance(line, LTTextLine):
                            # PDF的y轴是从下往上的,所以用-y来实现从上到下排序
                            y_position = -line.bbox[1]
                            x_position = line.bbox[0]
                            line_text = line.get_text().strip()
                            if line_text:
                                text_lines.append((y_position, x_position, line_text))
            
            # 先按垂直位置(从上到下),再按水平位置(从左到右)排序
            text_lines.sort(key=lambda item: (item[0], item[1]))
            
            # 生成带布局的页面文本
            page_content = []
            last_y = None
            for y, x, text in text_lines:
                # 遇到新的行就换行
                if y != last_y:
                    page_content.append('\n')
                    last_y = y
                # 用空格模拟水平缩进(这里按x坐标每5单位加一个空格,可按需调整)
                page_content.append(' ' * int(x // 5) + text)
            
            full_text.append(''.join(page_content))
    
    return '\n\n'.join(full_text)

代码说明

  1. PDFPageAggregator:替代原来的TextConverter,它会解析出PDF页面的布局结构,包括每个文本元素的位置、大小等信息。
  2. 坐标排序:利用PDF的坐标系统(y轴从下往上),通过-y_position实现从上到下的排序,再按x_position实现从左到右的排列。
  3. 模拟布局:通过计算文本行的x坐标,添加对应数量的空格来还原原有的缩进和分栏效果。如果需要更精确的对齐,可以进一步获取单个字符的宽度信息(LTChar对象的adv属性)来调整空格数。

另一种简便方法

如果不需要太精细的布局,也可以用pdfminer的高级API,设置layout_mode="layout":

from pdfminer.high_level import extract_text

text = extract_text("Wochenkarte-KW-15-Neu.pdf", layout_mode="layout")
print(text)

这个方法会直接输出带基本布局的文本,适合快速需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:07:34