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

如何使用pdfminer提取多PDF坐标文本并存储为列表/字典

修复多PDF文件坐标关联文本提取的存储问题

嘿,我看了你的代码,发现几个关键问题导致没法正确存储多个PDF的提取结果,咱们一步步来修复它:

原代码的核心问题

  • parse_obj函数定义在PDF文件循环内部,而且函数里错误地再次遍历所有PDF文件,逻辑完全混乱,会导致重复处理或者关联错误的文件。
  • 存储用的lst没有和单个PDF文件绑定,所有文件的内容会混在一起,你没法区分哪条数据属于哪个PDF。
  • 缺少全局存储结构(比如字典)来收集每个PDF的提取结果,处理完所有文件后拿不到最终数据。
  • 变量命名冲突:函数里的one_pdf和外层循环的当前PDF文件名变量重名,导致无法正确记录当前处理的文件。

修复后的代码

import os
import glob
from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfpage import PDFPage
from pdfminer.pdfpage import PDFTextExtractionNotAllowed
from pdfminer.pdfinterp import PDFResourceManager
from pdfminer.pdfinterp import PDFPageInterpreter
from pdfminer.pdfdevice import PDFDevice
from pdfminer.layout import LAParams
from pdfminer.converter import PDFPageAggregator
import pdfminer
from cStringIO import StringIO

# 全局存储结构:键是PDF文件名,值是该文件的所有文本坐标条目
pdf_extraction_results = {}

def parse_obj(lt_objs, current_file, page_num, result_list):
    """解析布局对象,提取坐标和文本,存入结果列表"""
    for obj in lt_objs:
        if isinstance(obj, pdfminer.layout.LTTextBoxHorizontal):
            # 提取坐标和文本,替换换行符
            text = obj.get_text().replace('\n', '_')
            coords = [obj.bbox[0], obj.bbox[1]]
            # 添加到当前文件的结果列表,同时记录页码
            result_list.append({
                'page': page_num,
                'coords': coords,
                'text': text
            })
            # 打印调试信息
            print(f"{current_file} - Page {page_num}: {coords[0]:6.2f}, {coords[1]:6.2f}, {text}")
        elif isinstance(obj, pdfminer.layout.LTFigure):
            # 递归处理子图形
            parse_obj(obj._objs, current_file, page_num, result_list)

# 获取目标文件夹下的所有PDF
directory = os.path.abspath('./')
pdf_files = glob.glob(os.path.join(directory, '*.pdf'))

# 初始化PDF处理资源
resource_manager = PDFResourceManager()
la_params = LAParams()
device = PDFPageAggregator(resource_manager, laparams=la_params)
interpreter = PDFPageInterpreter(resource_manager, device)

max_pages = 0
caching = True
page_nums = set()

# 遍历每个PDF文件
for pdf_path in pdf_files:
    print(f"Processing file: {pdf_path}")
    # 为当前PDF创建专属的结果列表
    current_pdf_results = []
    # 打开PDF文件
    with open(pdf_path, 'rb') as fp:
        # 遍历PDF的每一页(页码从1开始计数)
        for page_idx, page in enumerate(PDFPage.get_pages(fp, page_nums, maxpages=max_pages, caching=caching, check_extractable=True), start=1):
            interpreter.process_page(page)
            layout = device.get_result()
            # 解析当前页的布局对象,传入当前文件名、页码和结果列表
            parse_obj(layout._objs, pdf_path, page_idx, current_pdf_results)
    
    # 将当前PDF的结果存入全局字典
    pdf_extraction_results[pdf_path] = current_pdf_results

# 关闭设备
device.close()

# 示例:打印第一个PDF的前3条提取结果
if pdf_extraction_results:
    first_pdf = next(iter(pdf_extraction_results.keys()))
    print(f"\n示例:{first_pdf} 的提取结果(前3条):")
    for item in pdf_extraction_results[first_pdf][:3]:
        print(item)

关键修改说明

  1. 重构parse_obj函数:把它移到循环外面,接受当前文件名、页码和结果列表作为参数,避免变量冲突和逻辑混乱,递归处理子图形时也能正确传递上下文。
  2. 清晰的存储结构:用pdf_extraction_results字典存储每个PDF的结果,键是PDF完整路径,值是包含页码、坐标、文本的字典列表,结构清晰,便于后续处理。
  3. 资源管理优化:用with open()自动管理文件句柄,避免资源泄漏;页码从1开始计数,更符合用户阅读习惯。
  4. 变量命名规范:把模糊的变量名(比如one_pdf、lst)改成直观的pdf_path、current_pdf_results,避免命名冲突。

修改后你就能得到一个规整的嵌套结构(字典套列表套字典),所有PDF的提取结果都能被正确区分和存储,后续可以直接使用pdf_extraction_results来导出数据或者做进一步分析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:38:40