如何使用 Python 從 PDF 提取文字 (3 個函式庫比較)
從 PDF 提取文字看似簡單,但任何嘗試過的開發人員都知道,這是一個充滿例外、版面混亂和頑固的圖像式文件的領域。本指南將為您釐清這些困擾。我們將從直接比較最適合此任務的 Python 函式庫開始,讓您能立即為您的專案選擇正確的工具。

接著,我們將逐步介紹三個最有效的函式庫—PyPDF2、pdfplumber 和 PyMuPDF (Fitz)—的程式碼範例,涵蓋從基本文字抓取到處理複雜表格的所有內容。我們還將解決最艱鉅的挑戰:需要光學字元辨識 (OCR) 的掃描 PDF,並向您展示一種實用的方法來處理它們,而無需複雜的本地設定。最後,您將掌握程式碼和策略,可靠地自動化您的 PDF 處理工作流程。
快速評斷:最佳 PDF 文字提取 Python 函式庫
在我們深入程式碼之前,這裡是對主要競爭者的高層次概述。您的選擇將完全取決於您需要速度、簡潔性還是精確的版面分析。
| 函式庫 | 最適合 | 版面/表格處理 | 效能 | 易用性 (1-5) |
|---|---|---|---|---|
| PyPDF2 | 簡單、純文字文件;基本 PDF 操作(合併/分割) | 差(提取文字流,無位置資料) | 中等 | 5 |
| pdfplumber | 從表格提取資料;具有結構化版面的文件 | 極佳(提供文字、線條和矩形的座標) | 較慢 | 4 |
| PyMuPDF (Fitz) | 高速批次處理;處理圖像和註釋 | 良好(可提取帶有基本位置資訊的文字) | 極佳(最快) | 4 |
總結: 對於最簡單的情況,請從 PyPDF2 開始。一旦遇到表格,請轉向 pdfplumber。當效能是您的主要考量時,請選擇 PyMuPDF。
開始之前:設定您的 Python 環境
為了保持專案依賴項的整潔並避免衝突,請務必在虛擬環境中工作。這是任何嚴肅 Python 專案不可或缺的最佳實踐。
以下是如何在您的終端機中進行設定:
-
建立虛擬環境:
# On macOS/Linux python3 -m venv pdf_env # On Windows python -m venv pdf_env -
啟用它:
# On macOS/Linux source pdf_env/bin/activate # On Windows .\pdf_env\Scripts\activate您的終端機提示符現在應該顯示
(pdf_env)。 -
安裝函式庫: 我們將安裝所有三個我們正在比較的函式庫,以便您輕鬆進行實驗。
pip install pypdf2 pdfplumber pymupdf這樣,您的環境就準備好執行下面的程式碼範例了。
方法 1:使用 PyPDF2 進行基本文字提取
PyPDF2 是執行基本 PDF 操作的首選函式庫。它簡單易用,存在已久,非常適合文字可選取且非圖像部分的「原生」PDF。如果您的文件是簡單的報告、文章或基於文字的匯出,PyPDF2 將以最少的程式碼完成任務。
主要限制是什麼?它讀取 PDF 的內部文字流,這不一定與視覺閱讀順序一致,尤其是在多欄版面中。它也沒有表格的概念;它只會將所有單元格文字混雜在一起。
這是一個從 PDF 提取所有文字的簡單腳本:
# requirements: pip install pypdf2
import PyPDF2
def extract_text_with_pypdf2(pdf_path):
"""
Extracts text from a PDF file using the PyPDF2 library.
Args:
pdf_path (str): The file path to the PDF.
Returns:
str: The extracted text content, or an error message.
"""
try:
with open(pdf_path, 'rb') as file:
reader = PyPDF2.PdfReader(file)
num_pages = len(reader.pages)
print(f"Total pages: {num_pages}")
full_text = ""
for page_num in range(num_pages):
page = reader.pages[page_num]
full_text += page.extract_text() + "\n"
return full_text
except FileNotFoundError:
return f"Error: The file at {pdf_path} was not found."
except Exception as e:
return f"An unexpected error occurred: {e}"
# --- Usage Example ---
pdf_file = 'path/to/your/document.pdf'
extracted_text = extract_text_with_pypdf2(pdf_file)
if "Error" not in extracted_text:
print("--- Extracted Text ---")
print(extracted_text)
else:
print(extracted_text)
這個腳本對於簡單的單欄文字運作良好。但是當您給它一個帶有整齊表格的財務報表時會發生什麼?您會得到一堆沒有結構的文字和數字。這就是我們下一個函式庫大放異彩的地方。
方法 2:使用 pdfplumber 處理表格和版面
當您的任務涉及提取結構化資料時,pdfplumber 是正確的工具。它建立在 pdfminer.six 之上,旨在讓您精確存取 PDF 頁面的幾何結構。它「看見」字元、線條和矩形,並且具有出色的內建方法來偵測和提取表格。
這對於資料科學和業務自動化任務來說是一個遊戲規則的改變者。想像一下,嘗試從公司的 PDF 報告中提取季度收益。使用 PyPDF2,這將是字串解析的惡夢。使用 pdfplumber,您可以將資料作為一個乾淨的列表的列表獲取,準備好用於 Pandas DataFrame。
pdfplumber 在結構化資料方面優於 PyPDF2 的主要原因在於它能夠解釋視覺版面,而不僅僅是原始文字流。 它理解某些文字元素是按行和列對齊的,並由線條分隔。
以下是如何從 PDF 頁面提取表格:
# requirements: pip install pdfplumber
import pdfplumber
import pandas as pd
def extract_tables_with_pdfplumber(pdf_path, page_number=0):
"""
Extracts all tables from a specific page of a PDF using pdfplumber.
Args:
pdf_path (str): The file path to the PDF.
page_number (int): The page number to extract tables from (0-indexed).
Returns:
list of pandas.DataFrame: A list where each element is a DataFrame
representing a table found on the page.
"""
tables = []
try:
with pdfplumber.open(pdf_path) as pdf:
if page_number >= len(pdf.pages):
print(f"Error: Page {page_number} is out of range. The PDF has {len(pdf.pages)} pages.")
return tables
page = pdf.pages[page_number]
# .extract_tables() is the key method here
extracted_tables = page.extract_tables()
for table_data in extracted_tables:
# Convert the list of lists into a pandas DataFrame
df = pd.DataFrame(table_data[1:], columns=table_data[0])
tables.append(df)
return tables
except FileNotFoundError:
print(f"Error: The file at {pdf_path} was not found.")
return tables
except Exception as e:
print(f"An unexpected error occurred: {e}")
return tables
# --- Usage Example ---
# You'll need pandas for this example: pip install pandas
pdf_file_with_table = 'path/to/your/report.pdf'
all_tables = extract_tables_with_pdfplumber(pdf_file_with_table, page_number=0)
if all_tables:
print(f"Found {len(all_tables)} table(s) on page 0.")
for i, table_df in enumerate(all_tables):
print(f"\n--- Table {i+1} ---")
print(table_df)
else:
print("No tables found on the specified page.")
這種精確度的代價是速度。pdfplumber 在分析頁面方面做了更多工作,因此它本質上比那些只傾倒文字的函式庫慢。
方法 3:使用 PyMuPDF (Fitz) 進行高效能提取
當您需要快速處理數百或數千個 PDF 時,效能成為決定性因素。這正是 PyMuPDF(您將其匯入為 fitz)佔主導地位的地方。它是 MuPDF(一個輕量級 C 函式庫)的 Python 綁定,這使其速度極快。
我曾經有一個專案需要處理數千份多頁法律文件。我最初的 pdfplumber 腳本預計需要數小時。切換到 PyMuPDF 後,運行時間縮短到 30 分鐘以下。速度差異就是如此巨大。
除了速度之外,PyMuPDF 還是功能強大的工具。它可以將頁面渲染為圖像(對於 OCR 工作流程至關重要)、提取嵌入圖像並處理註釋。雖然它的表格提取功能不如 pdfplumber 那樣開箱即用,但其原始文字提取速度是無與倫比的。
這是 PyMuPDF 快速文字提取的等效方法:
# requirements: pip install PyMuPDF
import fitz # The PyMuPDF library
def extract_text_with_pymupdf(pdf_path):
"""
Extracts text from a PDF file using the high-performance PyMuPDF (Fitz) library.
Args:
pdf_path (str): The file path to the PDF.
Returns:
str: The extracted text content, or an error message.
"""
try:
doc = fitz.open(pdf_path)
full_text = ""
for page in doc:
# .get_text() is the core function
full_text += page.get_text() + "\n"
doc.close()
return full_text
except FileNotFoundError:
return f"Error: The file at {pdf_path} was not found."
except Exception as e:
# PyMuPDF can raise specific errors, e.g., fitz.fitz.FitzError
return f"An error occurred with PyMuPDF: {e}"
# --- Usage Example ---
pdf_file = 'path/to/your/document.pdf'
fast_extracted_text = extract_text_with_pymupdf(pdf_file)
if "Error" not in fast_extracted_text:
print("--- Extracted Text (Fast Method) ---")
print(fast_extracted_text)
else:
print(fast_extracted_text)
對於基於文字的 PDF 的純粹吞吐量而言,PyMuPDF 是無可爭議的冠軍。
特殊情況:使用 OCR 處理掃描 PDF
您可能會想:如果這些方法都不起作用會發生什麼?如果您在掃描文件(例如合約圖片或數位化書頁)上運行上述程式碼,您將得到一個空字串。
發生這種情況是因為沒有文字層。PDF 包含的是圖像,而不是字元。為了解決這個問題,您需要光學字元辨識 (OCR) 來「讀取」圖像並將其轉換為機器可讀的文字。
標準的 Python 解決方案是 pytesseract,它是 Google Tesseract OCR 引擎的包裝器。雖然功能強大,但它帶來了一個主要麻煩:您必須在系統上單獨安裝 Tesseract(例如,在 Mac 上透過 brew 或在 Windows 上透過安裝程式),並確保 Python 可以找到可執行檔。這種設定可能很脆弱,尤其是在將程式碼部署到伺服器或與同事共享時。
替代方案:使用無程式碼工具預處理複雜 PDF
當您時間緊迫或只是不想處理 OCR 依賴項的麻煩時,一個實用的替代方案是首先將文字提取卸載到專用工具。這將複雜的 OCR 問題與您的核心 Python 邏輯分開。
像 Lynote AI PDF 文字提取器 這樣的 AI 驅動工具可以作為強大的預處理器。您可以上傳您難以處理的掃描 PDF,它將在幕後處理 OCR,為您提供乾淨的文字,然後您可以將其輸入到您的腳本中。這對於一次性任務或處理少量有問題的文件特別有用。
以下是工作流程的簡單程度:
- 上傳您的 PDF 檔案。 導航到 Lynote 工作區。在「上傳檔案」選項卡中,您可以拖放您的 PDF 或瀏覽您的電腦來選擇它。這適用於基於文字和基於掃描圖像的 PDF。
- 從 PDF 提取文字。 檔案上傳後,點擊「建立筆記」按鈕。Lynote 的 AI 引擎會處理文件,如果偵測到基於圖像的檔案,會自動應用 OCR,並生成一個乾淨、可搜尋的文字版本。
- 複製提取的文字。 一旦文字出現在編輯器中,您可以審閱它,進行任何微小的更正,然後使用複製按鈕抓取整個內容。它現在已在您的剪貼簿中,準備好作為字串變數貼入您的 Python 腳本。


這種方法讓您可以專注於程式碼的資料分析部分,而不是本地 OCR 設定的基礎設施和錯誤處理。
常見陷阱和進階技巧
從 PDF 提取文字很少是一個完美的過程。以下是一些您可能會遇到的常見問題:
- 字元編碼: 您可能會遇到
UnicodeDecodeError。這通常發生在較舊的 PDF 或由不常見軟體生成的 PDF 上。大多數現代函式庫都能很好地處理UTF-8,但如果函式庫允許,指定編碼有時會有幫助。 - 受密碼保護的 PDF: 如果 PDF 需要密碼才能打開,所有這些函式庫都將失敗。您必須在打開過程中提供密碼。例如,
PyPDF2.PdfReader(file, password='your_password')。 - 格式遺失: 請記住,文字提取幾乎總是會遺失粗體、斜體、字體大小和顏色等格式。您獲得的是原始文字內容,而不是視覺呈現。
- 欄位文字混亂: 如 PyPDF2 所述,多欄版面(如學術論文中)可能會導致文字混雜來自不同欄位的行。
pdfplumber在分離這些方面做得更好,因為它理解頁面的幾何結構。
專家建議: 始終在您的文件代表性樣本上測試您的腳本。在一個 PDF 上完美運作的解決方案,可能在來自不同來源的另一個 PDF 上完全失敗。
常見問題
為什麼我從表格中提取的文字變成了一長串混亂的字串?
這是像 PyPDF2 這樣不分析頁面版面的函式庫的典型失敗模式。它們按照檔案中儲存的順序讀取原始文字流,這通常與視覺上的行和列結構不符。要解決這個問題,您必須使用像 **pdfplumber** 這樣具有版面感知能力的函式庫,它專門設計用於識別表格資料。
Python 可以從 PDF 頁面的特定區域提取文字嗎?
是的,但您需要一個提供座標資訊的函式庫。pdfplumber 和 PyMuPDF 在這方面表現出色。使用 pdfplumber,您可以使用 .crop((x0, top, x1, bottom)) 方法建立一個邊界框,然後只在該裁剪區域內運行 .extract_text() 或 .extract_tables()。
為什麼我的掃描 PDF 提取的文字是空的?
您的 PDF 包含的是文字圖像,而不是實際的文字資料。標準函式庫無法「讀取」圖像。您需要使用光學字元辨識 (OCR) 過程。您可以設定一個帶有 pytesseract 的本地 OCR 引擎,或者先使用像 Lynote 這樣的預處理工具將基於圖像的 PDF 轉換為乾淨的文字。
我如何處理多語言 PDF?
像 PyMuPDF 和 pdfplumber 這樣的現代函式庫通常能很好地處理 Unicode(支援大多數語言)。主要挑戰出現在 OCR 過程中。例如,Tesseract 要求您下載並指定您希望它使用的語言包(例如,-l eng+fra 用於英語和法語)。
結論:選擇正確的 Python PDF 工具
在 Python 中,沒有一個「最佳」的函式庫可以從 PDF 提取文字。正確的選擇總是取決於您的文件性質和專案目標。
讓我們將其歸結為一個簡單的決策樹:
- 如果您的 PDF 是簡單的、基於文字的文件,並且您只需要原始內容,那麼 PyPDF2 是最容易且最快實施的。
- 如果您的 PDF 包含表格或結構化版面,您需要將其解析為資料(例如,用於載入到資料庫或 Pandas DataFrame),那麼 pdfplumber 是明顯的贏家。
- 如果您正在處理大量文件,並且原始速度是您的首要任務,那麼 PyMuPDF (Fitz) 是最強大且效能最佳的選項。
- 如果您正在處理掃描的、基於圖像的 PDF,您必須使用 OCR。對於無需本地設定麻煩的快速可靠解決方案,在將乾淨文字引入您的 Python 環境之前,使用外部工具預處理檔案通常是最務實的方法。


