python实现简单提取PDF文档内文字

 更新时间:2026年02月06日 09:33:52   作者:geovindu  
这篇文章主要为大家详细介绍了如何使用python实现简单提取PDF文档内文字功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

本文介绍了一个私有化PDF文档问答系统的实现方案,重点解决了中文PDF解析和加密文件处理问题。系统采用pdfplumber替代PyPDF2进行文本提取,优化了对中文PDF的支持,并新增了加密PDF的密码输入和解密功能。系统提供用户友好的Web界面,包含文档上传、问题输入、回答生成和内容预览等功能,支持文本型PDF和加密PDF(需输入密码)的处理。

完整代码

# encoding: utf-8
# 版权所有 2024 ©涂聚文有限公司
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2023.1 python 3.11
# OS        : windows 10
# database  : mysql 9.0 sql server 2019, poostgreSQL 17.0  oracle 11g
# Datetime  : 2026/02/05 22:16
# User      : geovindu
# Product   : PyCharm
# Project   : pyOracleDemo
# File      : Main.py
# explain   : 学习
'''
https://github.com/gradio-app/gradio
https://modelscope.cn/models/ZhipuAI/GLM-OCR
https://www.gradio.app/custom-components/gallery
pip install gradio -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install streamlit -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install pypdf2 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install PyCryptodome -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install pdfplumber -i https://pypi.tuna.tsinghua.edu.cn/simple


'''
import gradio as gr
import os
import tempfile
import streamlit as st
#from PyPDF2 import PdfReader, errors as PyPDF2Errors
from typing import Optional
from typing import List
import pdfplumber  # 替换PyPDF2
import traceback


class DocumentQASystem:
    """私有化PDF文档问答系统(修复is_encrypted属性错误)"""

    def __init__(self):
        st.set_page_config(
            page_title="私有化文档问答系统",
            layout="wide",
            initial_sidebar_state="collapsed"
        )
        if "doc_text" not in st.session_state:
            st.session_state.doc_text = ""
        self._set_custom_style()

    def _set_custom_style(self):
        st.markdown("""
            <style>
            .stButton>button {width: 100%; margin-top: 10px;}
            .stTextInput>div>div>input {padding: 8px;}
            .doc-preview {max-height: 400px; overflow-y: auto; border: 1px solid #eee; padding: 10px; border-radius: 5px;}
            </style>
        """, unsafe_allow_html=True)

    def _extract_pdf_text(self, pdf_path: str) -> str:
        """
        修复:移除错误的is_encrypted判断,适配pdfplumber加密PDF处理逻辑
        核心:pdfplumber打开加密PDF会抛异常,捕获后引导输入密码
        """
        full_text = ""
        try:
            # 第一步:尝试直接打开PDF(非加密PDF直接处理)
            try:
                with pdfplumber.open(pdf_path) as pdf:
                    # 逐页提取文本(中文友好)
                    for page_num, page in enumerate(pdf.pages, 1):
                        text = page.extract_text()
                        if text:
                            full_text += f"\n=== 第 {page_num} 页 ===\n{text}\n"

            # 第二步:捕获加密PDF异常,引导输入密码
            except pdfplumber.utils.PDFEncryptionError:
                st.warning("检测到该PDF文件已加密,请输入解密密码")
                pdf_password = st.text_input(
                    "PDF解密密码",
                    type="password",
                    key="pdf_pwd",
                    help="输入密码后会自动重新解析"
                )
                # 有密码时尝试解密打开
                if pdf_password:
                    try:
                        with pdfplumber.open(pdf_path, password=pdf_password) as pdf:
                            for page_num, page in enumerate(pdf.pages, 1):
                                text = page.extract_text()
                                if text:
                                    full_text += f"\n=== 第 {page_num} 页 ===\n{text}\n"
                    except Exception:
                        st.error("密码错误!请输入正确的PDF解密密码")
                        return ""
                else:
                    st.info("请输入密码后重试解析")
                    return ""

            return full_text.strip()

        except ImportError:
            st.error("依赖缺失:请执行 `pip install pdfplumber` 安装解析库")
            return ""
        except Exception as e:
            # 打印详细错误(仅调试用,可注释)
            st.error(f"PDF解析失败:{str(e)}")
            st.debug(f"详细错误信息:{traceback.format_exc()}")
            return ""

    def _mock_llm_answer(self, question: str, context: str) -> str:
        return f"【回答】:针对问题“{question}”,上下文中检索到相关内容:{context[:100]}..."

    def render_ui(self):
        st.title("📄 文档问答工具(中文PDF优化+加密修复版)")
        st.divider()

        col1, col2 = st.columns([1, 2])
        with col1:
            st.subheader("📤 文档上传与提问")
            uploaded_file = st.file_uploader("选择PDF文档", type=["pdf"])

            if uploaded_file is not None:
                with st.spinner("正在解析PDF(中文优化版)..."):
                    # 临时文件处理
                    with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_file:
                        tmp_file.write(uploaded_file.read())
                        tmp_path = tmp_file.name

                    # 提取文本(核心修复后的方法)
                    st.session_state.doc_text = self._extract_pdf_text(tmp_path)

                    # 清理临时文件(增加异常捕获)
                    try:
                        os.unlink(tmp_path)
                    except Exception as e:
                        st.warning(f"临时文件清理失败:{str(e)}(不影响功能)")

                    if st.session_state.doc_text:
                        st.success(f"✅ PDF解析成功!提取字符总数:{len(st.session_state.doc_text)}")

            # 清空文档按钮
            if st.button("🗑️ 清空已上传文档", type="secondary"):
                st.session_state.doc_text = ""
                st.rerun()

            st.divider()
            # 用户提问
            question = st.text_input(
                "💡 请输入你要查询的问题",
                placeholder="例如:文档中提到的核心结论是什么?",
                disabled=not st.session_state.doc_text
            )
            # 提交按钮(仅当有文档和问题时可用)
            submit_btn = st.button(
                "🚀 提交问题生成回答",
                type="primary",
                disabled=not (question and st.session_state.doc_text)
            )

        with col2:
            st.subheader("📋 结果展示")
            # 显示回答
            if submit_btn:
                with st.spinner("正在基于文档内容生成回答..."):
                    answer = self._mock_llm_answer(question, st.session_state.doc_text)
                    st.markdown("### 🎯 回答结果")
                    st.write(answer)
                    st.divider()

            # 文档内容预览
            if st.session_state.doc_text:
                st.markdown("### 📄 文档内容预览(前1500字符)")
                st.markdown(
                    f'<div class="doc-preview">{st.session_state.doc_text[:1500]}...</div>',
                    unsafe_allow_html=True
                )
            else:
                st.info("📌 请先上传PDF文档,支持中文文本型PDF、加密PDF(需输入密码)")

        # 底部提示
        st.divider()
        st.caption("💡 注意:扫描件PDF(纯图片)无法提取文本,需先进行OCR识别;文本型PDF均可正常解析")


def main():
    """程序主入口函数"""
    # 实例化问答系统并渲染界面
    qa_system = DocumentQASystem()
    qa_system.render_ui()
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    print('hello world')
    main()


在终端运行:

# 2. 用Streamlit专用命令启动(关键!)
streamlit run Main.py

方法补充

下面是小编整理的python提取PDF内容的其他方法,希望对大家有所帮助

1. Python提取指定页文字

import pdfplumber
 
path = './练习文件/文字.pdf'
# with语句:打开文件不用手动关闭,但要注意缩进
with pdfplumber.open(path) as pdf:
    # # 获取首页
    first_page = pdf.pages[0]
    # 将指定页提取文字
    text = first_page.extract_text()
    textW = open('./结果文件/1.txt', mode='a', encoding='utf-8')
    textW.write(text)

2. Python提取所有页面文字

import pdfplumber
 
path = './练习文件/文字.pdf'
with pdfplumber.open(path) as pdf:
    for page in pdf.pages:
        # 将每页提取文字
        text = page.extract_text()
        textW = open('./结果文件/2.txt', mode='a', encoding='utf-8')
        textW.write(text)

3.Python从特定PDF页面提取文本

从指定的PDF页面提取文本,大致步骤如下:

  • 加载PDF文档。
  • 通过页面索引获取指定页面。
  • 提取页面的文本内容。
  • 将提取的文本保存到文本文件中。

代码:

from spire.pdf.common import *
from spire.pdf import *

# 定义一个从PDF文档指定页面提取文本的函数,参数分别为输入PDF文档的路径,需要提取文本的页面索引(从0开始),存放提取文本的文本文档的路径
def extract_text_from_page(file_path, page_num, output_file):
    # 创建PdfDocument类的实例
    doc = PdfDocument()
    # 加载PDF文档
    doc.LoadFromFile(file_path)

    # 根据页面索引获取特定页面
    page = doc.Pages[page_num]

    # 从该页面提取文本
    text = page.ExtractText(True)

    # 将提取的文本存储到文本文件
    with open(output_file, "w", encoding="utf-8") as text_file:
        text_file.write(text)

    doc.Close()

# 调用函数实现从PDF指定页面提取文本
file_path = "测试.pdf"
page_num = 0  # 指定从中提取文本的页码(页码索引从0开始)
output_file = "提取页面文本.txt"
extract_text_from_page(file_path, page_num, output_file)

4.Python从特定PDF页面区域提取文本

从指定PDF页面区域提取文本,大致步骤如下:

  • 加载PDF文档。
  • 通过页面索引获取指定页面。
  • 指定需要提取文本内容的矩形区域的坐标、宽度和高度。
  • 从页面的指定矩形区域中提取文本。
  • 将提取的文本保存到文本文件中。

代码:

from spire.pdf.common import *
from spire.pdf import *

# 定义一个从PDF文档指定页面的指定区域提取文本的函数,参数分别为输入PDF文档的路径,需要提取文本的页面索引(从0开始),区域的X坐标,区域的Y坐标,区域的宽度,区域的高度,存放提取文本的文本文件路径
def extract_text_from_page_area(file_path, page_num, x, y, width, height, output_file):
    # 创建PdfDocument实例
    doc = PdfDocument()
    # 加载PDF文档
    doc.LoadFromFile(file_path)

    # 根据页面索引获取特定页面
    page = doc.Pages[page_num]

    # 定义一个矩形来指定文本提取的区域
    rectangle = RectangleF(x, y, width, height)

    # 从页面的指定矩形区域中提取文本
    text = page.ExtractText(rectangle)

    # 将提取的文本存储到文本文件
    with open(output_file, "w", encoding="utf-8") as text_file:
        text_file.write(text)

    doc.Close()

# 调用函数实现从PDF指定页面的指定区域提取文本
file_path = "测试.pdf"
page_num = 0  # 指定从中提取文本的页码(页码索引从0开始)
x = 0.0
y = 180.0
width = 500.0
height = 200.0
output_file = "提取页面区域文本.txt"
extract_text_from_page_area(file_path, page_num, x, y, width, height, output_file)

到此这篇关于python实现简单提取PDF文档内文字的文章就介绍到这了,更多相关python提取PDF文字内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python的列表和元组详情

    Python的列表和元组详情

    这篇文章主要介绍了Python的列表和元组,列表和元组是python组常见的内置内省,下面文章我们讲围绕Python的列表和元组的相关资料展开话题,感兴趣的小伙伴以参考一下
    2021-10-10
  • Python编程itertools模块处理可迭代集合相关函数

    Python编程itertools模块处理可迭代集合相关函数

    本篇博客将为你介绍Python函数式编程itertools模块中处理可迭代集合的相关函数,有需要的朋友可以借鉴参考下,希望可以有所帮助
    2021-09-09
  • python abs函数用法小结

    python abs函数用法小结

    abs()是python的内置函数,它的作用是返回一个数的绝对值,abs函数的主要用途是返回一个数的绝对值,下面通过本文给大家分享python abs函数怎么用,感兴趣的朋友一起看看吧
    2024-05-05
  • Python如何处理多分隔符的字符串拆分

    Python如何处理多分隔符的字符串拆分

    在数据爆炸时代,字符串解析是每个Python开发者必备的核心技能,本文将深入解析Python中多分隔符字符串拆分的完整技术体系,需要的小伙伴可以参考下
    2025-08-08
  • 基于Python闭包及其作用域详解

    基于Python闭包及其作用域详解

    下面小编就为大家带来一篇基于Python闭包及其作用域详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • pytorch 准备、训练和测试自己的图片数据的方法

    pytorch 准备、训练和测试自己的图片数据的方法

    这篇文章主要介绍了pytorch 准备、训练和测试自己的图片数据的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • Python中argparse模块命令行参数详细解析

    Python中argparse模块命令行参数详细解析

    本文系统介绍Python argparse模块,涵盖其核心功能:解析命令行参数、自动生成帮助文档、支持位置参数与可选参数、提供类型验证及错误处理、实现子命令系统等,帮助开发者创建用户友好的命令行工具,需要的朋友跟随小编一起学习吧
    2025-08-08
  • Python实现将一个带键值特征的JSON数组转换为JSON对象

    Python实现将一个带键值特征的JSON数组转换为JSON对象

    这篇文章主要为大家详细介绍了Python实现将一个带键值特征的JSON数组转换为JSON对象,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下
    2025-11-11
  • 一文理解Python命名机制

    一文理解Python命名机制

    这篇文章主要介绍的是Python的命名机制,文章回先提出问题,然后根据问题逐步解析,感兴趣的小伙伴可以参考一下,希望对你有所帮助
    2021-10-10
  • po+selenium+unittest自动化测试项目实战

    po+selenium+unittest自动化测试项目实战

    本文主要介绍了po+selenium+unittest自动化测试项目实战,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12

最新评论