python實現簡單提取PDF文檔內文字
本文介紹了一個私有化PDF文檔問答系統的實現方案,重點解決了中文PDF解析和加密文件處理問題。系統采用pdfplumber替代PyPDF2進行文本提取,優(yōu)化了對中文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("依賴缺失:請執(zhí)行 `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優(yōu)化+加密修復版)")
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(中文優(yōu)化版)..."):
# 臨時文件處理
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):
# 創(chuàng)建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頁面區(qū)域提取文本
從指定PDF頁面區(qū)域提取文本,大致步驟如下:
- 加載PDF文檔。
- 通過頁面索引獲取指定頁面。
- 指定需要提取文本內容的矩形區(qū)域的坐標、寬度和高度。
- 從頁面的指定矩形區(qū)域中提取文本。
- 將提取的文本保存到文本文件中。
代碼:
from spire.pdf.common import *
from spire.pdf import *
# 定義一個從PDF文檔指定頁面的指定區(qū)域提取文本的函數,參數分別為輸入PDF文檔的路徑,需要提取文本的頁面索引(從0開始),區(qū)域的X坐標,區(qū)域的Y坐標,區(qū)域的寬度,區(qū)域的高度,存放提取文本的文本文件路徑
def extract_text_from_page_area(file_path, page_num, x, y, width, height, output_file):
# 創(chuàng)建PdfDocument實例
doc = PdfDocument()
# 加載PDF文檔
doc.LoadFromFile(file_path)
# 根據頁面索引獲取特定頁面
page = doc.Pages[page_num]
# 定義一個矩形來指定文本提取的區(qū)域
rectangle = RectangleF(x, y, width, height)
# 從頁面的指定矩形區(qū)域中提取文本
text = page.ExtractText(rectangle)
# 將提取的文本存儲到文本文件
with open(output_file, "w", encoding="utf-8") as text_file:
text_file.write(text)
doc.Close()
# 調用函數實現從PDF指定頁面的指定區(qū)域提取文本
file_path = "測試.pdf"
page_num = 0 # 指定從中提取文本的頁碼(頁碼索引從0開始)
x = 0.0
y = 180.0
width = 500.0
height = 200.0
output_file = "提取頁面區(qū)域文本.txt"
extract_text_from_page_area(file_path, page_num, x, y, width, height, output_file)
到此這篇關于python實現簡單提取PDF文檔內文字的文章就介紹到這了,更多相關python提取PDF文字內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python argparse中的action=store_true用法小結
這篇文章主要介紹了Python argparse中的action=store_true用法小結,本文結合示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-02-02
用python + openpyxl處理excel2007文檔思路以及心得
最近要幫做RA的老姐寫個合并excel工作表的腳本……源數據是4000+個excel 工作表,分布在9個xlsm文件里,文件內容是中英文混雜的一些數據,需要從每張表中提取需要的部分,分門別類合并到多個大的表里。2014-07-07
Python實現在PyPI上發(fā)布自定義軟件包的方法詳解
在Python中我們經常使用pip來安裝第三方Python軟件包,其實我們每個人都可以免費地將自己寫的Python包發(fā)布到PyPI上。本文我們就將詳細介紹如何發(fā)布測試包,需要的可以參考一下2022-06-06
Python基于identicon庫創(chuàng)建類似Github上用的頭像功能
這篇文章主要介紹了Python基于identicon庫創(chuàng)建類似Github上用的頭像功能,結合具體實例形式分析了identicon庫操作圖形的具體步驟與相關使用技巧,需要的朋友可以參考下2017-09-09

