Python使用PDFPlumber提取PDF內(nèi)容的操作指南
引言
處理PDF文件時(shí),你是否遇到過這些難題:想復(fù)制表格卻格式錯(cuò)亂?提取文本時(shí)段落被拆得支離破碎?手動(dòng)錄入PDF數(shù)據(jù)效率低下還易出錯(cuò)?如果你用過PyPDF2、pdfminer等庫,可能會(huì)發(fā)現(xiàn)它們在處理復(fù)雜布局(尤其是表格)時(shí)力不從心。
而 pdfplumber 的出現(xiàn),完美解決了這些痛點(diǎn)。它是一個(gè)專注于PDF內(nèi)容提取的Python庫,以“精準(zhǔn)還原布局”為核心優(yōu)勢,能輕松提取文本、表格,甚至獲取文字的位置、字體等細(xì)節(jié)信息。本文將從基礎(chǔ)用法到實(shí)戰(zhàn)場景,全方位講解pdfplumber的使用,幫你徹底告別PDF處理的繁瑣。
一、為什么選擇pdfplumber?
在眾多PDF處理庫中,pdfplumber的核心競爭力在于:
- 表格提取精準(zhǔn):自動(dòng)識(shí)別表格邊框、合并單元格,提取結(jié)果保留表格結(jié)構(gòu)(類似Excel),遠(yuǎn)超PyPDF2等庫的“純文本拼接”。
- 文本提取智能:按頁面布局還原文本順序,避免段落被無序拆分,還能獲取文字的坐標(biāo)、字體、大小等元數(shù)據(jù)。
- 操作簡單直觀:API設(shè)計(jì)簡潔,幾行代碼即可完成提取,無需深入了解PDF底層格式。
- 支持細(xì)節(jié)控制:可指定提取區(qū)域(如只提取某頁的某塊內(nèi)容)、過濾無效信息,靈活應(yīng)對復(fù)雜PDF。
適合場景:數(shù)據(jù)分析師提取PDF報(bào)表、開發(fā)者批量處理合同文本、研究者抓取文獻(xiàn)內(nèi)容等。
二、環(huán)境準(zhǔn)備:1分鐘安裝
pdfplumber是純Python庫,安裝無需依賴復(fù)雜的系統(tǒng)工具,直接用pip即可:
pip install pdfplumber
驗(yàn)證安裝是否成功:
import pdfplumber print(pdfplumber.__version__) # 輸出版本號(hào)(如 0.9.0)即成功
三、基礎(chǔ)用法:從加載PDF到提取內(nèi)容
pdfplumber的核心流程是:**加載PDF文件→獲取頁面→提取內(nèi)容(文本/表格)**。我們從最基礎(chǔ)的操作開始,逐步掌握核心功能。
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"頁面旋轉(zhuǎn)角度:{first_page.rotation}°") # 0表示正常,90/180表示旋轉(zhuǎn)
print(f"是否包含圖片:{len(first_page.images) > 0}")說明:用with語句加載PDF可自動(dòng)釋放資源,避免文件占用;pages是一個(gè)列表,pdf.pages[0]表示第1頁,pdf.pages[-1]表示最后一頁。
2. 提取文本:保留布局與細(xì)節(jié)
pdfplumber提取文本的核心方法是extract_text(),它會(huì)按頁面布局還原文本順序,比其他庫更貼近“人眼所見”。
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("該頁面無文本內(nèi)容(可能是掃描版PDF)")進(jìn)階:獲取文本的位置與樣式
如果需要更詳細(xì)的信息(如文字坐標(biāo)、字體、大小),可用extract_words():
with pdfplumber.open("example.pdf") as pdf:
page = pdf.pages[0]
# 提取頁面中所有文字的詳細(xì)信息(列表 of 字典)
words = page.extract_words()
# 打印前3個(gè)文字的信息
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")用途:可用于判斷標(biāo)題(通常字體更大)、提取特定區(qū)域的文本(如根據(jù)坐標(biāo)過濾)。
3. 提取表格:自動(dòng)識(shí)別結(jié)構(gòu)(核心優(yōu)勢)
pdfplumber最強(qiáng)大的功能是提取表格,extract_table()和extract_tables()方法能自動(dòng)識(shí)別表格邊框,輸出結(jié)構(gòu)化的列表(每行是一個(gè)子列表),直接可用pandas轉(zhuǎn)為DataFrame。
示例1:提取單個(gè)表格
import pdfplumber
import pandas as pd
with pdfplumber.open("report.pdf") as pdf:
page = pdf.pages[2] # 假設(shè)第3頁有一個(gè)表格
# 提取表格(返回列表 of 列表)
table = page.extract_table()
if table:
# 用pandas轉(zhuǎn)為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:提取頁面中所有表格
如果一頁有多個(gè)表格,用extract_tables()(注意多了個(gè)s),返回表格列表:
with pdfplumber.open("multi_tables.pdf") as pdf:
page = pdf.pages[0]
# 提取所有表格(返回列表 of 表格)
all_tables = page.extract_tables()
print(f"頁面中共檢測到 {len(all_tables)} 個(gè)表格")
# 遍歷每個(gè)表格并保存
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ù)
復(fù)雜表格(如無明顯邊框、合并單元格)可能需要調(diào)整參數(shù),常用參數(shù):
table_settings={"vertical_strategy": "lines", "horizontal_strategy": "lines"}:指定表格邊框識(shí)別策略(lines=按線條,text=按文本間距)。snakeize=True:自動(dòng)將表頭轉(zhuǎn)為蛇形命名(如“用戶ID”→“user_id”)。
示例:處理無明顯邊框的表格:
table = page.extract_table(
table_settings={
"vertical_strategy": "text", # 按文本垂直間距識(shí)別列
"horizontal_strategy": "text" # 按文本水平間距識(shí)別行
}
)4. 提取指定區(qū)域的內(nèi)容
如果只需提取PDF中某塊區(qū)域(如左上角的標(biāo)題、右下角的簽名),可通過坐標(biāo)框選區(qū)域。
import pdfplumber
with pdfplumber.open("invoice.pdf") as pdf:
page = pdf.pages[0]
# 定義區(qū)域:(x0, top, x1, bottom),即左上角x、y和右下角x、y
# 可通過pdfplumber的可視化工具查看坐標(biāo)(后文介紹)
area = (50, 50, 400, 150) # 示例區(qū)域(需根據(jù)實(shí)際PDF調(diào)整)
# 提取指定區(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ū)域坐標(biāo)?
推薦用pdfplumber自帶的可視化工具:運(yùn)行pdfplumber-cli inspect example.pdf,在瀏覽器中打開鏈接,鼠標(biāo)框選區(qū)域即可顯示坐標(biāo)。
四、實(shí)戰(zhàn)場景:解決實(shí)際問題
掌握基礎(chǔ)后,我們來看幾個(gè)實(shí)用場景,直接復(fù)用代碼即可解決工作中的PDF處理需求。
場景1:批量提取多頁P(yáng)DF的文本到TXT
將一個(gè)多頁P(yáng)DF的所有文本提取到單個(gè)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中所有頁面的表格提取后,合并到一個(gè)Excel的不同工作表:
import pdfplumber
import pandas as pd
from openpyxl import load_workbook
def extract_all_tables_to_excel(pdf_path, excel_path):
"""提取PDF中所有表格到Excel的多個(gè)工作表"""
with pdfplumber.open(pdf_path) as pdf:
# 創(chuàng)建一個(gè)Excel寫入器
writer = pd.ExcelWriter(excel_path, engine="openpyxl")
table_count = 0 # 統(tǒng)計(jì)總表格數(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
# 轉(zhuǎn)換為DataFrame
try:
df = pd.DataFrame(table[1:], columns=table[0])
except:
# 處理無表頭的表格
df = pd.DataFrame(table)
# 工作表名稱:頁面_表格序號(hào)
sheet_name = f"頁{page_num}_表{i}"
# 寫入Excel(超過31字符會(huì)被截?cái)啵杼幚恚?
df.to_excel(writer, sheet_name=sheet_name[:31], index=False)
print(f"已提?。簕sheet_name}")
writer.close()
print(f"所有表格(共{table_count}個(gè))已保存到 {excel_path}")
# 用法:提取所有表格到all_tables.xlsx
extract_all_tables_to_excel("multi_page_report.pdf", "all_tables.xlsx")場景3:提取發(fā)票中的關(guān)鍵信息(如金額、日期)
針對格式固定的發(fā)票PDF,提取指定區(qū)域的關(guān)鍵信息(如發(fā)票號(hào)、金額、日期):
import pdfplumber
def extract_invoice_info(pdf_path):
"""提取發(fā)票中的關(guān)鍵信息"""
with pdfplumber.open(pdf_path) as pdf:
page = pdf.pages[0] # 發(fā)票通常只有1頁
# 定義各信息的區(qū)域(需根據(jù)實(shí)際發(fā)票調(diào)整坐標(biāo))
regions = {
"發(fā)票號(hào)": (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ū)域坐標(biāo)不同,可先用pdfplumber-cli inspect工具獲取準(zhǔn)確坐標(biāo)。
場景4:處理掃描版PDF(需結(jié)合OCR)
注意:pdfplumber只能提取**文本型PDF**(由文字組成),無法直接處理**掃描版PDF**(本質(zhì)是圖片)。此時(shí)需先用OCR工具(如pytesseract)將圖片轉(zhuǎn)為文本,再用pdfplumber處理。
示例:結(jié)合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頁面轉(zhuǎn)為圖片
img = page.to_image().original # 獲取PIL Image對象
# 用OCR識(shí)別圖片中的文本
text = pytesseract.image_to_string(img, lang="chi_sim") # 中文識(shí)別
# 寫入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官網(wǎng)。
五、避坑指南:常見問題與解決方案
提取的文本亂碼或缺失
- 原因:PDF字體編碼特殊,或文本被圖片覆蓋。
- 解決:嘗試用
page.extract_text(x_tolerance=1, y_tolerance=1)調(diào)整 tolerance 參數(shù);若仍亂碼,可能是掃描版PDF,需結(jié)合OCR。
表格提取錯(cuò)亂(行列不對齊)
- 原因:表格無明顯邊框,或存在合并單元格。
- 解決:調(diào)整
table_settings參數(shù),如{"vertical_strategy": "text", "horizontal_strategy": "text"};或手動(dòng)指定表格區(qū)域(crop后再提取)。
大文件處理緩慢或內(nèi)存溢出
- 原因:一次性加載整個(gè)PDF占用內(nèi)存大。
- 解決:分頁處理,提取一頁釋放一頁資源:
with pdfplumber.open("large.pdf") as pdf:
for page in pdf.pages:
# 處理當(dāng)前頁...
text = page.extract_text()
# 處理完后無需保留page對象無法提取加密PDF
- 原因:PDF被加密(需密碼才能打開)。
- 解決:先解密PDF(可用
qpdf工具),再用pdfplumber處理:qpdf --decrypt input.pdf output.pdf。
六、總結(jié):PDF處理,選對工具事半功倍
pdfplumber憑借精準(zhǔn)的文本和表格提取能力,成為Python處理PDF的首選庫之一。它的核心優(yōu)勢在于:
- 對表格的提取能力遠(yuǎn)超同類庫,幾乎能還原Excel般的結(jié)構(gòu);
- 提供豐富的細(xì)節(jié)控制(區(qū)域提取、樣式獲?。?,靈活應(yīng)對復(fù)雜場景;
- 代碼簡潔易上手,無需深入了解PDF底層原理。
如果你需要處理文本型PDF(尤其是包含表格的報(bào)表、發(fā)票、合同),pdfplumber能幫你節(jié)省大量手動(dòng)錄入時(shí)間。對于掃描版PDF,可結(jié)合OCR工具形成完整解決方案。
以上就是Python使用PDFPlumber提取PDF內(nèi)容的操作指南的詳細(xì)內(nèi)容,更多關(guān)于Python PDFPlumber提取PDF的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python連接oracle數(shù)據(jù)庫操作實(shí)例及遇到的異常
這篇文章主要給大家介紹了關(guān)于python連接oracle數(shù)據(jù)庫操作實(shí)例及遇到的一些異常,Oracle是著名且廣泛使用的數(shù)據(jù)庫之一,而python的數(shù)據(jù)處理功能可以很好地利用這種連接性,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
關(guān)于Python 內(nèi)置庫 itertools
今天得這篇文章就來給大家介紹一下Python的系統(tǒng)庫itertools的 相關(guān)資料,需要的小伙伴可以參考下面文章的具體內(nèi)容2021-09-09
Python定時(shí)任務(wù)工具之APScheduler使用方式
APScheduler (advanceded python scheduler)是一款Python開發(fā)的定時(shí)任務(wù)工具。這篇文章主要介紹了Python定時(shí)任務(wù)工具--APScheduler的使用方式,需要的朋友可以參考下2019-07-07
解決Python中的modf()函數(shù)取小數(shù)部分不準(zhǔn)確問題
這篇文章主要介紹了解決Python中的modf()函數(shù)取小數(shù)部分不準(zhǔn)確問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-05-05

