Python使用PDFPlumber提取PDF內容的操作指南
引言
處理PDF文件時,你是否遇到過這些難題:想復制表格卻格式錯亂?提取文本時段落被拆得支離破碎?手動錄入PDF數(shù)據(jù)效率低下還易出錯?如果你用過PyPDF2、pdfminer等庫,可能會發(fā)現(xiàn)它們在處理復雜布局(尤其是表格)時力不從心。
而 pdfplumber 的出現(xiàn),完美解決了這些痛點。它是一個專注于PDF內容提取的Python庫,以“精準還原布局”為核心優(yōu)勢,能輕松提取文本、表格,甚至獲取文字的位置、字體等細節(jié)信息。本文將從基礎用法到實戰(zhàn)場景,全方位講解pdfplumber的使用,幫你徹底告別PDF處理的繁瑣。
一、為什么選擇pdfplumber?
在眾多PDF處理庫中,pdfplumber的核心競爭力在于:
- 表格提取精準:自動識別表格邊框、合并單元格,提取結果保留表格結構(類似Excel),遠超PyPDF2等庫的“純文本拼接”。
- 文本提取智能:按頁面布局還原文本順序,避免段落被無序拆分,還能獲取文字的坐標、字體、大小等元數(shù)據(jù)。
- 操作簡單直觀:API設計簡潔,幾行代碼即可完成提取,無需深入了解PDF底層格式。
- 支持細節(jié)控制:可指定提取區(qū)域(如只提取某頁的某塊內容)、過濾無效信息,靈活應對復雜PDF。
適合場景:數(shù)據(jù)分析師提取PDF報表、開發(fā)者批量處理合同文本、研究者抓取文獻內容等。
二、環(huán)境準備:1分鐘安裝
pdfplumber是純Python庫,安裝無需依賴復雜的系統(tǒng)工具,直接用pip即可:
pip install pdfplumber
驗證安裝是否成功:
import pdfplumber print(pdfplumber.__version__) # 輸出版本號(如 0.9.0)即成功
三、基礎用法:從加載PDF到提取內容
pdfplumber的核心流程是:**加載PDF文件→獲取頁面→提取內容(文本/表格)**。我們從最基礎的操作開始,逐步掌握核心功能。
1. 加載PDF并查看頁面信息
首先需要用pdfplumber.open()加載PDF文件,然后通過pages屬性獲取所有頁面(按頁碼順序排列)。
import pdfplumber
# 加載PDF文件
with pdfplumber.open("example.pdf") as pdf:
# 查看PDF基本信息
print(f"總頁數(shù):{len(pdf.pages)}") # 輸出總頁數(shù)
# 獲取第一頁(索引從0開始)
first_page = pdf.pages[0]
# 查看頁面屬性
print(f"頁面尺寸:{first_page.width} x {first_page.height} 像素")
print(f"頁面旋轉角度:{first_page.rotation}°") # 0表示正常,90/180表示旋轉
print(f"是否包含圖片:{len(first_page.images) > 0}")說明:用with語句加載PDF可自動釋放資源,避免文件占用;pages是一個列表,pdf.pages[0]表示第1頁,pdf.pages[-1]表示最后一頁。
2. 提取文本:保留布局與細節(jié)
pdfplumber提取文本的核心方法是extract_text(),它會按頁面布局還原文本順序,比其他庫更貼近“人眼所見”。
import pdfplumber
with pdfplumber.open("example.pdf") as pdf:
# 提取第2頁文本
page = pdf.pages[1] # 第2頁(索引1)
text = page.extract_text()
# 打印提取的文本(前500字符)
if text:
print("提取的文本:")
print(text[:500] + "...") # 只顯示前500字符
else:
print("該頁面無文本內容(可能是掃描版PDF)")進階:獲取文本的位置與樣式
如果需要更詳細的信息(如文字坐標、字體、大?。?,可用extract_words():
with pdfplumber.open("example.pdf") as pdf:
page = pdf.pages[0]
# 提取頁面中所有文字的詳細信息(列表 of 字典)
words = page.extract_words()
# 打印前3個文字的信息
for word in words[:3]:
print(f"文字:{word['text']}")
print(f"位置:x={word['x0']:.2f}, y={word['top']:.2f}(左上角)")
print(f"大?。簩?{word['width']:.2f}, 高={word['height']:.2f}")
print(f"字體:{word.get('fontname', '未知')}, 大小={word.get('size', '未知')}\n")用途:可用于判斷標題(通常字體更大)、提取特定區(qū)域的文本(如根據(jù)坐標過濾)。
3. 提取表格:自動識別結構(核心優(yōu)勢)
pdfplumber最強大的功能是提取表格,extract_table()和extract_tables()方法能自動識別表格邊框,輸出結構化的列表(每行是一個子列表),直接可用pandas轉為DataFrame。
示例1:提取單個表格
import pdfplumber
import pandas as pd
with pdfplumber.open("report.pdf") as pdf:
page = pdf.pages[2] # 假設第3頁有一個表格
# 提取表格(返回列表 of 列表)
table = page.extract_table()
if table:
# 用pandas轉為DataFrame(方便后續(xù)處理)
df = pd.DataFrame(table[1:], columns=table[0]) # 第0行為表頭
print("提取的表格:")
print(df.head()) # 打印前5行
# 保存為Excel
df.to_excel("extracted_table.xlsx", index=False)
else:
print("未檢測到表格")示例2:提取頁面中所有表格
如果一頁有多個表格,用extract_tables()(注意多了個s),返回表格列表:
with pdfplumber.open("multi_tables.pdf") as pdf:
page = pdf.pages[0]
# 提取所有表格(返回列表 of 表格)
all_tables = page.extract_tables()
print(f"頁面中共檢測到 {len(all_tables)} 個表格")
# 遍歷每個表格并保存
for i, table in enumerate(all_tables):
if table:
df = pd.DataFrame(table[1:], columns=table[0])
df.to_excel(f"table_{i+1}.xlsx", index=False)
print(f"表格 {i+1} 已保存")自定義表格提取參數(shù)
復雜表格(如無明顯邊框、合并單元格)可能需要調整參數(shù),常用參數(shù):
table_settings={"vertical_strategy": "lines", "horizontal_strategy": "lines"}:指定表格邊框識別策略(lines=按線條,text=按文本間距)。snakeize=True:自動將表頭轉為蛇形命名(如“用戶ID”→“user_id”)。
示例:處理無明顯邊框的表格:
table = page.extract_table(
table_settings={
"vertical_strategy": "text", # 按文本垂直間距識別列
"horizontal_strategy": "text" # 按文本水平間距識別行
}
)4. 提取指定區(qū)域的內容
如果只需提取PDF中某塊區(qū)域(如左上角的標題、右下角的簽名),可通過坐標框選區(qū)域。
import pdfplumber
with pdfplumber.open("invoice.pdf") as pdf:
page = pdf.pages[0]
# 定義區(qū)域:(x0, top, x1, bottom),即左上角x、y和右下角x、y
# 可通過pdfplumber的可視化工具查看坐標(后文介紹)
area = (50, 50, 400, 150) # 示例區(qū)域(需根據(jù)實際PDF調整)
# 提取指定區(qū)域的文本
region_text = page.crop(area).extract_text()
print("指定區(qū)域的文本:")
print(region_text)
# 提取指定區(qū)域的表格(如果有的話)
region_table = page.crop(area).extract_table()
if region_table:
print("指定區(qū)域的表格:")
for row in region_table:
print(row)如何獲取區(qū)域坐標?
推薦用pdfplumber自帶的可視化工具:運行pdfplumber-cli inspect example.pdf,在瀏覽器中打開鏈接,鼠標框選區(qū)域即可顯示坐標。
四、實戰(zhàn)場景:解決實際問題
掌握基礎后,我們來看幾個實用場景,直接復用代碼即可解決工作中的PDF處理需求。
場景1:批量提取多頁PDF的文本到TXT
將一個多頁PDF的所有文本提取到單個TXT文件,按頁碼分隔:
import pdfplumber
def pdf_to_txt(pdf_path, txt_path):
"""將PDF所有頁面的文本提取到TXT"""
with pdfplumber.open(pdf_path) as pdf, open(txt_path, "w", encoding="utf-8") as f:
for i, page in enumerate(pdf.pages, start=1):
text = page.extract_text()
if text:
f.write(f"=== 第 {i} 頁 ===\n")
f.write(text + "\n\n")
print(f"文本已提取到 {txt_path}")
# 用法:提取report.pdf的文本到report.txt
pdf_to_txt("report.pdf", "report.txt")場景2:提取PDF中的所有表格并合并到Excel
將PDF中所有頁面的表格提取后,合并到一個Excel的不同工作表:
import pdfplumber
import pandas as pd
from openpyxl import load_workbook
def extract_all_tables_to_excel(pdf_path, excel_path):
"""提取PDF中所有表格到Excel的多個工作表"""
with pdfplumber.open(pdf_path) as pdf:
# 創(chuàng)建一個Excel寫入器
writer = pd.ExcelWriter(excel_path, engine="openpyxl")
table_count = 0 # 統(tǒng)計總表格數(shù)
for page_num, page in enumerate(pdf.pages, start=1):
tables = page.extract_tables()
if not tables:
continue
for i, table in enumerate(tables, start=1):
table_count += 1
# 轉換為DataFrame
try:
df = pd.DataFrame(table[1:], columns=table[0])
except:
# 處理無表頭的表格
df = pd.DataFrame(table)
# 工作表名稱:頁面_表格序號
sheet_name = f"頁{page_num}_表{i}"
# 寫入Excel(超過31字符會被截斷,需處理)
df.to_excel(writer, sheet_name=sheet_name[:31], index=False)
print(f"已提?。簕sheet_name}")
writer.close()
print(f"所有表格(共{table_count}個)已保存到 {excel_path}")
# 用法:提取所有表格到all_tables.xlsx
extract_all_tables_to_excel("multi_page_report.pdf", "all_tables.xlsx")場景3:提取發(fā)票中的關鍵信息(如金額、日期)
針對格式固定的發(fā)票PDF,提取指定區(qū)域的關鍵信息(如發(fā)票號、金額、日期):
import pdfplumber
def extract_invoice_info(pdf_path):
"""提取發(fā)票中的關鍵信息"""
with pdfplumber.open(pdf_path) as pdf:
page = pdf.pages[0] # 發(fā)票通常只有1頁
# 定義各信息的區(qū)域(需根據(jù)實際發(fā)票調整坐標)
regions = {
"發(fā)票號": (350, 120, 500, 140), # x0, top, x1, bottom
"開票日期": (350, 150, 500, 170),
"總金額": (350, 300, 500, 320)
}
info = {}
for key, area in regions.items():
# 裁剪區(qū)域并提取文本
text = page.crop(area).extract_text()
# 清洗文本(去除空格、換行)
if text:
info[key] = text.replace("\n", "").strip()
else:
info[key] = "未找到"
return info
# 用法:提取發(fā)票信息
invoice_info = extract_invoice_info("invoice.pdf")
print("發(fā)票信息:")
for key, value in invoice_info.items():
print(f"{key}:{value}")提示:不同發(fā)票的區(qū)域坐標不同,可先用pdfplumber-cli inspect工具獲取準確坐標。
場景4:處理掃描版PDF(需結合OCR)
注意:pdfplumber只能提取**文本型PDF**(由文字組成),無法直接處理**掃描版PDF**(本質是圖片)。此時需先用OCR工具(如pytesseract)將圖片轉為文本,再用pdfplumber處理。
示例:結合OCR提取掃描版PDF的文本:
import pdfplumber
import pytesseract
from PIL import Image
def ocr_scanned_pdf(pdf_path, txt_path):
"""提取掃描版PDF的文本(需安裝Tesseract OCR)"""
with pdfplumber.open(pdf_path) as pdf, open(txt_path, "w", encoding="utf-8") as f:
for i, page in enumerate(pdf.pages, start=1):
# 將PDF頁面轉為圖片
img = page.to_image().original # 獲取PIL Image對象
# 用OCR識別圖片中的文本
text = pytesseract.image_to_string(img, lang="chi_sim") # 中文識別
# 寫入TXT
f.write(f"=== 第 {i} 頁 ===\n")
f.write(text + "\n\n")
print(f"掃描版PDF文本已提取到 {txt_path}")
# 用法(需先安裝Tesseract并配置環(huán)境變量):
# ocr_scanned_pdf("scanned_invoice.pdf", "scanned_text.txt")前置條件:需安裝Tesseract OCR引擎和pytesseract庫,具體步驟參考Tesseract官網。
五、避坑指南:常見問題與解決方案
提取的文本亂碼或缺失
- 原因:PDF字體編碼特殊,或文本被圖片覆蓋。
- 解決:嘗試用
page.extract_text(x_tolerance=1, y_tolerance=1)調整 tolerance 參數(shù);若仍亂碼,可能是掃描版PDF,需結合OCR。
表格提取錯亂(行列不對齊)
- 原因:表格無明顯邊框,或存在合并單元格。
- 解決:調整
table_settings參數(shù),如{"vertical_strategy": "text", "horizontal_strategy": "text"};或手動指定表格區(qū)域(crop后再提?。?/li>
大文件處理緩慢或內存溢出
- 原因:一次性加載整個PDF占用內存大。
- 解決:分頁處理,提取一頁釋放一頁資源:
with pdfplumber.open("large.pdf") as pdf:
for page in pdf.pages:
# 處理當前頁...
text = page.extract_text()
# 處理完后無需保留page對象無法提取加密PDF
- 原因:PDF被加密(需密碼才能打開)。
- 解決:先解密PDF(可用
qpdf工具),再用pdfplumber處理:qpdf --decrypt input.pdf output.pdf。
六、總結:PDF處理,選對工具事半功倍
pdfplumber憑借精準的文本和表格提取能力,成為Python處理PDF的首選庫之一。它的核心優(yōu)勢在于:
- 對表格的提取能力遠超同類庫,幾乎能還原Excel般的結構;
- 提供豐富的細節(jié)控制(區(qū)域提取、樣式獲?。?,靈活應對復雜場景;
- 代碼簡潔易上手,無需深入了解PDF底層原理。
如果你需要處理文本型PDF(尤其是包含表格的報表、發(fā)票、合同),pdfplumber能幫你節(jié)省大量手動錄入時間。對于掃描版PDF,可結合OCR工具形成完整解決方案。
以上就是Python使用PDFPlumber提取PDF內容的操作指南的詳細內容,更多關于Python PDFPlumber提取PDF的資料請關注腳本之家其它相關文章!
相關文章
Pytorch-mlu?實現(xiàn)添加逐層算子方法詳解
本文主要分享了在寒武紀設備上?pytorch-mlu?中添加逐層算子的方法教程,代碼具有一定學習價值,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-11-11
淺談python3發(fā)送post請求參數(shù)為空的情況
今天小編就為大家分享一篇淺談python3發(fā)送post請求參數(shù)為空的情況,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-12-12

