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

使用Python的PDFMiner提取PDF全页文本存JSON:仅提取首页问题求助

问题:PDF多页文本提取仅获取第一页,如何合并所有页面到JSON?

我尝试将PDF文件的所有页面合并为单个文本并保存至JSON文件,程序无报错但仅能提取PDF的第一页文本。请问如何遍历PDF文件并将所有页面文本追加到JSON文件中?感谢您的提示。

你的原代码:

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
import io
from io import StringIO
from io import BytesIO
import os
import glob
import json

pdf_path = 'pdfs'
pdfFiles = [os.path.join(pdf_path, f) for f in os.listdir(pdf_path) if f.endswith(".pdf") if os.path.isfile(os.path.join(pdf_path, f))]
extractTextFromPdf(pdfFiles[0])

def extractTextFromPdfByPage(pdf_path):
    with open(pdf_path, 'rb') as fh:
        resourceManager = PDFResourceManager()
        returnString = StringIO()
        codec = 'utf-8'
        laParams = LAParams()
        device = TextConverter(resourceManager, returnString, codec=codec, laparams=laParams)
        filename = os.path.splitext(os.path.basename(pdf_path))[0]
        for page in PDFPage.get_pages(fh, caching=True, check_extractable=True):
            resource_manager = PDFResourceManager()
            fake_file_handle = io.StringIO()
            converter = TextConverter(resource_manager, fake_file_handle)
            page_interpreter = PDFPageInterpreter(resource_manager, converter)
            page_interpreter.process_page(page)
            text = fake_file_handle.getvalue()
            yield text
            converter.close()
            fake_file_handle.close()
        data = {'id': filename, 'text': text}
        json_path = 'stage0.json'
        with open(json_path, 'w') as fh:
            json.dump(data, fh)
        return text
        device.close()
        returnString.close()

def extractTextFromPdf(pdf_path):
    for page in extractTextFromPdfByPage(pdf_path):
        print(page)
        print()

问题分析

我看了你的代码,核心问题有这几点:

  1. 生成器逻辑导致文本丢失:extractTextFromPdfByPage是生成器函数,yield text会暂停函数执行,循环外的JSON写入代码要等所有页面迭代完才会运行,但此时text变量只保留了最后一页的内容,前面页面的文本都没被收集。
  2. 重复创建资源浪费且易出错:你在每一页循环里都重新创建PDFResourceManager、TextConverter等,不仅低效,还导致每一页的文本无法累加。
  3. 未合并所有页面文本:没有一个变量来存储所有页面的文本,最后只把单页文本写入了JSON。

修正后的代码方案

下面给你两种方案,按需选择:

方案一:直接合并所有页面文本(简洁高效)

这个方案去掉了不必要的生成器,直接在函数里完成所有页面的文本提取和合并,适合不需要逐页单独处理的场景:

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
import io
import os
import json

def extractTextFromPdf(pdf_path):
    # 初始化资源管理器和文本转换器
    resource_manager = PDFResourceManager()
    text_buffer = io.StringIO()
    converter = TextConverter(resource_manager, text_buffer, laparams=LAParams())
    page_interpreter = PDFPageInterpreter(resource_manager, converter)
    
    all_page_text = ""
    with open(pdf_path, 'rb') as pdf_file:
        for page in PDFPage.get_pages(pdf_file, caching=True, check_extractable=True):
            page_interpreter.process_page(page)
            # 获取当前页面文本并追加到总文本
            page_text = text_buffer.getvalue()
            all_page_text += page_text
            # 清空缓冲区,避免重复读取之前的页面内容
            text_buffer.truncate(0)
            text_buffer.seek(0)
    
    # 关闭资源,避免内存泄漏
    converter.close()
    text_buffer.close()
    
    # 准备JSON数据并写入文件
    pdf_filename = os.path.splitext(os.path.basename(pdf_path))[0]
    json_data = {'id': pdf_filename, 'text': all_page_text}
    
    with open('stage0.json', 'w', encoding='utf-8') as json_file:
        json.dump(json_data, json_file, ensure_ascii=False, indent=4)
    
    return all_page_text

# 调用示例
if __name__ == "__main__":
    pdf_dir = 'pdfs'
    pdf_files = [
        os.path.join(pdf_dir, file) 
        for file in os.listdir(pdf_dir) 
        if file.endswith(".pdf") and os.path.isfile(os.path.join(pdf_dir, file))
    ]
    if pdf_files:
        extractTextFromPdf(pdf_files[0])

方案二:保留生成器(适合需要逐页处理的场景)

如果你需要对每一页文本做单独处理(比如逐页解析、日志记录),可以保留生成器,再在外部收集所有页面文本:

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
import io
import os
import json

def extractTextFromPdfByPage(pdf_path):
    resource_manager = PDFResourceManager()
    with open(pdf_path, 'rb') as pdf_file:
        for page in PDFPage.get_pages(pdf_file, caching=True, check_extractable=True):
            text_buffer = io.StringIO()
            converter = TextConverter(resource_manager, text_buffer, laparams=LAParams())
            page_interpreter = PDFPageInterpreter(resource_manager, converter)
            
            page_interpreter.process_page(page)
            page_text = text_buffer.getvalue()
            
            # 关闭当前页的资源
            converter.close()
            text_buffer.close()
            
            yield page_text

def extractTextFromPdf(pdf_path):
    all_page_text = ""
    # 遍历生成器,收集所有页面文本
    for idx, page_text in enumerate(extractTextFromPdfByPage(pdf_path), 1):
        print(f"第{idx}页文本:\n{page_text}\n")
        all_page_text += page_text + "\n\n"  # 用换行分隔不同页面
    
    # 写入JSON文件
    pdf_filename = os.path.splitext(os.path.basename(pdf_path))[0]
    json_data = {'id': pdf_filename, 'text': all_page_text}
    
    with open('stage0.json', 'w', encoding='utf-8') as json_file:
        json.dump(json_data, json_file, ensure_ascii=False, indent=4)
    
    return all_page_text

# 调用示例
if __name__ == "__main__":
    pdf_dir = 'pdfs'
    pdf_files = [
        os.path.join(pdf_dir, file) 
        for file in os.listdir(pdf_dir) 
        if file.endswith(".pdf") and os.path.isfile(os.path.join(pdf_dir, file))
    ]
    if pdf_files:
        extractTextFromPdf(pdf_files[0])

关键修改点说明

  • 统一资源管理:把PDFResourceManager等核心资源移到循环外,避免重复创建,提升效率。
  • 文本累加机制:用all_page_text变量存储所有页面的文本,确保内容不丢失。
  • 缓冲区清空:处理完每一页后清空StringIO的缓冲区,防止后续页面重复读取之前的内容。
  • 合理的JSON写入时机:确保所有页面文本收集完成后,再写入JSON文件,保证数据完整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:35:18