使用Python實(shí)現(xiàn)PDF文檔自動化的操作大全(一鍵合并、分割、水印、提取與加密解密)
PDF文件難管理,編輯受限,手動操作低效!
在職場中,PDF文件因其格式穩(wěn)定、跨平臺兼容性好而廣泛應(yīng)用。但你有沒有被PDF的這些“痛點(diǎn)”折磨過?
文件零散: 多個相關(guān)的PDF文件(如項(xiàng)目周報、合同附件),散落在不同地方,難以整合為一個完整文檔。
編輯受限: 想從PDF中提取文字,卻發(fā)現(xiàn)無法復(fù)制;想修改某個數(shù)字,卻無從下手。
合并/分割麻煩: 需要把幾份PDF合并成一份,或者把一份長PDF拆分成多個小文件,手動操作效率低下。
缺乏保護(hù): 重要PDF文件直接傳輸,沒有密碼保護(hù),傳輸安全有隱患。
這些重復(fù)、低效的PDF文件管理任務(wù),嚴(yán)重拖慢了你的辦公自動化進(jìn)程
今天,我將帶你進(jìn)入Python處理PDF的奇妙世界!我們將手把手教你如何利用強(qiáng)大的Python庫,輕松
實(shí)現(xiàn):
PDF合并與分割: 批量操作,輕松整理文檔。
PDF文本提?。?瞬間獲取PDF中的文字信息。
PDF水印與頁碼: 批量添加,提升文檔專業(yè)度。
PDF加密解密: 為你的重要文檔加上“安全鎖”。
最終,你將擁有一個強(qiáng)大的PDF全能管家。
1.Python PDF處理庫選擇:PyPDF2與PyMuPDF對比
要實(shí)現(xiàn)Python處理PDF,有兩個非常流行的庫可供選擇:PyPDF2和PyMuPDF。了解它們的特點(diǎn),能幫你選擇最適合你需求的Python PDF庫。
1.1 PyPDF2:輕量易用,處理PDF文本和基本操作
PyPDF2: 更輕量級,主要用于PDF的結(jié)構(gòu)化操作(如合并、分割、提取文本/元數(shù)據(jù))。
1.2 PyMuPDF:功能強(qiáng)大,渲染與高級編輯
PyMuPDF (fitz): 功能更強(qiáng)大,除了結(jié)構(gòu)化操作,還具備高性能的PDF渲染(轉(zhuǎn)換為圖片)、高級文本和圖片提取、以及更精細(xì)的頁面編輯能力。
pip install PyPDF2 pip install PyMuPDF
1.3 環(huán)境準(zhǔn)備與選擇建議
表格:PyPDF2 與 PyMuPDF (fitz) 功能對比]
| 特性 | PyPDF2 | PyMuPDF (fitz) |
|---|---|---|
| 主要功能 | 合并、分割、旋轉(zhuǎn)、加密、基礎(chǔ)文本/頁面提取 | 渲染、文本/圖片/矢量圖形提取、高級插入、格式轉(zhuǎn)換 |
| 合并PDF | ? 支持 | ? 支持 |
| 分割PDF | ? 支持 | ? 支持 |
| 提取文本 | ? 支持(純文本) | ? 支持(含坐標(biāo)、格式) |
| 提取圖片 | ? 不支持 | ? 支持 |
| PDF轉(zhuǎn)圖片 | ? 不支持 | ? 支持 (高性能渲染) |
| 添加水印 | ? 支持(簡單文本/圖片) | ? 支持(高級:文本/圖片,字體、透明度可控) |
| 添加頁碼 | ? 不支持 | ? 支持 |
| 加密解密 | ? 支持(簡單密碼) | ? 支持(多種加密算法) |
| 內(nèi)容替換 | ? 不支持 | ? 支持 |
| 復(fù)雜編輯 | ? 不支持 | ? 支持 |
| 安裝/學(xué)習(xí) | 簡單 | 稍復(fù)雜/陡峭 |
| 適用場景 | 簡單的PDF合并、分割、加密、提取 | PDF預(yù)覽、高級文本/圖片提取、文檔渲染、PDF生成 |
選擇建議:
如果你只是想簡單合并、分割PDF,提取純文本:PyPDF2已足夠,因?yàn)樗唵?,易于快速上手?/p>
如果你需要進(jìn)行PDF渲染(如將Excel內(nèi)容“畫”到PDF)、高級文本/圖片提取、添加定制水印、或者更
精細(xì)的PDF內(nèi)容操作:強(qiáng)烈推薦PyMuPDF。
本文接下來的例子將主要基于PyMuPDF進(jìn)行演示,因?yàn)樗δ芨?,能?shí)現(xiàn)更多高級自動化。
2.Python批量合并與分割PDF文件,輕松整理文檔!
PDF文檔的合并與分割,是日常PDF自動化中最高頻的需求。Python能幫你一鍵完成這些操作,讓你的文檔管理自動化效率翻倍!
作用: PyMuPDF將PDF視為一系列頁面,可以方便地添加頁面(合并)或提取頁面(分割)。
2.1 批量合并PDF文件:一鍵拼接,文檔歸一
場景: 你有合同-附件1.pdf、合同-附件2.pdf和合同-正文.pdf,需要將它們按順序合并成一份完整的完整合同.pdf。
方案: 編寫一個Python腳本,指定多個源PDF文件,PyMuPDF將它們快速拼接成一個大的PDF文檔,實(shí)現(xiàn)PDF合并的自動化。
代碼:
import fitz # PyMuPDF庫
import os
def merge_pdfs(pdf_list, output_pdf_path):
"""
批量合并多個PDF文件為一個PDF文件。
這是Python處理PDF和PDF合并分割的核心功能。
:param pdf_list: 要合并的PDF文件路徑列表
:param output_pdf_path: 合并后PDF文件的輸出路徑
"""
if not pdf_list:
print("? 沒有指定任何PDF文件進(jìn)行合并。")
return False
os.makedirs(os.path.dirname(output_pdf_path), exist_ok=True)
print(f"?? 正在合并 {len(pdf_list)} 個PDF文件到 '{os.path.basename(output_pdf_path)}'...")
# 創(chuàng)建一個新的PDF文檔
new_pdf = fitz.open()
try:
for pdf_path in pdf_list:
if not os.path.exists(pdf_path):
print(f"?? 文件不存在,跳過:{os.path.basename(pdf_path)}")
continue
# 打開每個PDF文件,并將其所有頁面插入到新PDF中
with fitz.open(pdf_path) as doc:
new_pdf.insert_pdf(doc) # 插入PDF的所有頁面
print(f" ? 已合并:{os.path.basename(pdf_path)}")
new_pdf.save(output_pdf_path) # 保存合并后的PDF
print(f"? PDF合并成功!結(jié)果保存到:'{output_pdf_path}'")
return True
except Exception as e:
print(f"? PDF合并失?。簕e}")
return False
finally:
new_pdf.close() # 確保關(guān)閉PDF對象
if __name__ == "__main__":
# 準(zhǔn)備測試PDF文件
pdf1_path = os.path.expanduser("~/Desktop/report_part1.pdf")
pdf2_path = os.path.expanduser("~/Desktop/report_part2.pdf")
output_merged_pdf = os.path.expanduser("~/Desktop/merged_annual_report.pdf")
# 簡單創(chuàng)建模擬PDF文件 (實(shí)際請用你的真實(shí)PDF)
if not os.path.exists(pdf1_path):
doc1 = fitz.open(); doc1.new_page().insert_text(fitz.Point(50,50), "這是第一部分"); doc1.save(pdf1_path); doc1.close()
if not os.path.exists(pdf2_path):
doc2 = fitz.open(); doc2.new_page().insert_text(fitz.Point(50,50), "這是第二部分"); doc2.save(pdf2_path); doc2.close()
pdfs_to_merge = [pdf1_path, pdf2_path]
merge_pdfs(pdfs_to_merge, output_merged_pdf)
步驟:
安裝PyMuPDF: pip install PyMuPDF。
準(zhǔn)備PDF文件: 在桌面創(chuàng)建report_part1.pdf和report_part2.pdf等測試PDF文件。
修改代碼路徑: 修改 pdfs_to_merge 列表中的路徑和 output_merged_pdf。
運(yùn)行: 運(yùn)行 python merge_pdfs.py。
效果展示:

2.2 單個PDF文件按頁分割:長篇文檔秒變小冊子!
場景: 你收到一份50頁的PDF報告,但你只需要其中的第5頁到第10頁,或者想把每一頁都拆分成單獨(dú)的PDF文件。手動操作耗時且容易出錯。
方案: PyMuPDF能讓你精確地將一個多頁P(yáng)DF文件按頁碼范圍分割成多個獨(dú)立的PDF文件,或者將每一頁都拆分成單獨(dú)的文件。
代碼:
import fitz # PyMuPDF
import os
def split_pdf_by_pages(input_pdf_path, output_folder, page_ranges=None):
"""
將單個PDF文件按頁碼范圍分割為多個PDF文件。
這是Python處理PDF和PDF合并分割的高級功能。
:param input_pdf_path: 源PDF文件路徑
:param output_folder: 分割后PDF文件的輸出文件夾
:param page_ranges: 要分割的頁碼范圍列表,例如 [[0, 2], [5, 5]] 表示分割第1-3頁和第6頁
頁碼從0開始計(jì)數(shù)。如果為None,則每頁生成一個PDF。
"""
if not os.path.exists(input_pdf_path):
print(f"? PDF文件不存在:{input_pdf_path}")
return False
os.makedirs(output_folder, exist_ok=True)
print(f"?? 正在分割PDF文件 '{os.path.basename(input_pdf_path)}'...")
try:
with fitz.open(input_pdf_path) as doc:
if page_ranges is None: # 如果沒有指定范圍,則每頁分割一個PDF
page_ranges = [[i, i] for i in range(doc.page_count)]
for i, (start_page, end_page) in enumerate(page_ranges):
if start_page < 0 or end_page >= doc.page_count or start_page > end_page:
print(f"?? 頁碼范圍無效,跳過:[{start_page}, {end_page}]")
continue
# 創(chuàng)建新PDF來存儲分割的頁面
new_pdf = fitz.open()
new_pdf.insert_pdf(doc, from_page=start_page, to_page=end_page)
output_filename = f"{os.path.splitext(os.path.basename(input_pdf_path))[0]}_part_{i+1}_pages_{start_page+1}-{end_page+1}.pdf"
output_full_path = os.path.join(output_folder, output_filename)
new_pdf.save(output_full_path)
new_pdf.close()
print(f" ? 已分割:'{output_filename}' (頁碼: {start_page+1}-{end_page+1})")
print(f"? PDF分割完成!結(jié)果保存到:'{output_folder}'")
return True
except Exception as e:
print(f"? PDF分割失?。簕e}")
return False
if __name__ == "__main__":
# 準(zhǔn)備測試PDF文件 (多頁)
long_report_path = os.path.expanduser("~/Desktop/long_report.pdf")
# 簡單創(chuàng)建模擬PDF文件 (例如創(chuàng)建5頁的PDF)
if not os.path.exists(long_report_path):
doc = fitz.open()
for i in range(5):
page = doc.new_page(width=595, height=842) # A4
page.insert_text(fitz.Point(50,50), f"這是第 {i+1} 頁")
doc.save(long_report_path); doc.close()
output_split_folder = os.path.expanduser("~/Desktop/分割后PDF")
# 示例1:將每一頁分割為單獨(dú)的文件
print("\n--- 示例1:按頁分割所有PDF ---")
split_pdf_by_pages(long_report_path, os.path.join(output_split_folder, "ByPage"))
# 示例2:按指定范圍分割 (例如,只取第2頁到第4頁,對應(yīng)索引1到3)
print("\n--- 示例2:按頁碼范圍分割PDF (取第2到4頁) ---")
split_pdf_by_pages(long_report_path, os.path.join(output_split_folder, "Range"), page_ranges=[[1, 3]]) # 頁碼索引是0-based,范圍是[start, end)
操作步驟:
安裝PyMuPDF: pip install PyMuPDF。
準(zhǔn)備PDF文件: 在桌面創(chuàng)建long_report.pdf(包含多頁內(nèi)容,如5頁)。
修改代碼路徑和頁碼范圍: 修改 long_report_path 和 output_split_folder。
運(yùn)行: 運(yùn)行 python split_pdfs.py。
效果展示:

3. Python為PDF添加水印、頁碼與實(shí)現(xiàn)加密解密!
PDF的保護(hù)和專業(yè)化是文檔管理的重要環(huán)節(jié)。
PyMuPDF能讓你為PDF添加水印、自動生成頁碼,甚至進(jìn)行PDF加密與解密,全方位提升你的PDF自動化能力!
3.1 PDF水?。禾砑游淖帧D片Logo,保護(hù)文檔版權(quán)!
場景: 你需要為一份重要報告或內(nèi)部資料添加“絕密”、“版權(quán)所有”等文字水印,或在每頁添加你的公司名稱。
方案: PyMuPDF可以精確地在PDF的每一頁上添加文字水印或圖片水印,并控制其位置、透明度等。
代碼:
import fitz # PyMuPDF
from PIL import Image, ImageDraw, ImageFont # 用于文字渲染到圖片 (如果需要),或處理Logo圖片
import os
import io # 用于內(nèi)存中的文件操作
# 定義一個中文字體路徑,確保你的系統(tǒng)中有,否則中文可能顯示為方塊
CHINESE_FONT_PATH = "C:/Windows/Fonts/simhei.ttf" # Windows黑體示例
def add_pdf_watermark(pdf_path, output_path, watermark_type="text",
text_content="", font_size=30, text_color=(0.5, 0.5, 0.5), # RGB (0.0-1.0)
image_watermark_path=None, image_opacity=0.3, image_size_ratio=0.1,
position="bottom_right", rotate_degree=0): # 新增旋轉(zhuǎn)參數(shù)
"""
為PDF文件添加文字水印或圖片水印。
這是PDF自動化和PDF加水印的核心功能。
:param pdf_path: 源PDF文件路徑
:param output_path: 輸出PDF文件路徑
:param watermark_type: "text" (文字水印) 或 "image" (圖片水印)
:param text_content: 文字水印內(nèi)容
:param font_size: 文字水印字體大小
:param text_color: 文字水印顏色 (RGB元組,范圍0.0-1.0)
:param image_watermark_path: 圖片水印文件路徑
:param image_opacity: 圖片水印透明度 (0.0-1.0)
:param image_size_ratio: 圖片水印相對于頁面寬度的比例
:param position: 水印位置 ("top_left", "top_right", "bottom_left", "bottom_right", "center")
:param rotate_degree: 文字水印旋轉(zhuǎn)角度 (度)
"""
if not os.path.exists(pdf_path): return print(f"? PDF文件不存在:{pdf_path}")
os.makedirs(os.path.dirname(output_path), exist_ok=True)
doc = fitz.open(pdf_path) # 打開PDF文檔
print(f"?? 正在為 '{os.path.basename(pdf_path)}' 添加水印...")
# 嘗試加載中文字體
font_name_in_pdf = "helv" # 默認(rèn)內(nèi)置字體
if pdf_font_path and os.path.exists(CHINESE_FONT_PATH):
try:
# register_font 返回字體對象的xref,可以直接用于insert_text
font_xref = doc.register_font(fontfile=CHINESE_FONT_PATH, fontname="MyCustomFont")
font_name_in_pdf = "MyCustomFont"
print(f" ?? 已注冊自定義字體 '{font_name_in_pdf}'。")
except Exception as e:
print(f"?? 注冊中文字體失敗:{e}。中文水印可能無法正確顯示。")
# 加載圖片水?。ㄡ槍D片水?。?
watermark_img_obj = None
if watermark_type == "image":
if not os.path.exists(image_watermark_path):
print(f"? 水印圖片文件不存在:{image_watermark_path}")
return False
try:
watermark_img_obj = Image.open(image_watermark_path).convert("RGBA")
print(f" ?? 已加載水印圖片:{os.path.basename(image_watermark_path)}")
except Exception as e:
print(f"? 無法加載水印圖片:{e}")
return False
for page_num in range(doc.page_count):
page = doc.load_page(page_num)
rect = page.rect # 獲取頁面矩形
if watermark_type == "text":
# 插入文字水印
# 注意:fitz.insert_text直接處理透明度和顏色 (R,G,B浮點(diǎn)數(shù)0.0-1.0)
# 計(jì)算文字尺寸和位置 (需要實(shí)際渲染才能準(zhǔn)確獲取,這里估算)
# fitz.Font().text_bbox() 更精確,但需先實(shí)例化Font
text_len_estimate = fitz.Font(fontname=font_name_in_pdf).text_bbox(text_content, fontsize=font_size)[2]
text_height_estimate = font_size * 1.2 # 粗略估算高度
x, y = 0, 0
if position == "top_left": x, y = rect.x0 + 20, rect.y0 + 20
elif position == "top_right": x, y = rect.x1 - text_len_estimate - 20, rect.y0 + 20
elif position == "bottom_left": x, y = rect.x0 + 20, rect.y1 - text_height_estimate - 20
elif position == "bottom_right": x, y = rect.x1 - text_len_estimate - 20, rect.y1 - text_height_estimate - 20
elif position == "center": x, y = (rect.width - text_len_estimate) / 2, (rect.height - text_height_estimate) / 2
# 使用 insert_text
page.insert_text(
(x, y),
text_content,
fontname=font_name_in_pdf,
fontsize=font_size,
color=text_color, # 顏色為RGB浮點(diǎn)元組 (0.0, 0.0, 0.0) 到 (1.0, 1.0, 1.0)
# rotate=rotate_degree, # 旋轉(zhuǎn)在insert_text中不直接支持,需要transform矩陣
overlay=True, # 確保水印在內(nèi)容之上
)
# 對于旋轉(zhuǎn),需要更復(fù)雜的PyMuPDF變換矩陣,這里為簡潔不展開
elif watermark_type == "image" and watermark_img_obj:
# 插入圖片水印
page_width, page_height = rect.width, rect.height
# 調(diào)整水印圖片大小 (相對于頁面寬度比例)
wm_width = int(page_width * image_size_ratio)
wm_height = int(wm_width * watermark_img_obj.height / watermark_img_obj.width) # 保持比例
# 確保水印不超出頁面且有最小尺寸
if wm_width == 0 or wm_height == 0:
print(f"?? 水印尺寸計(jì)算為零,跳過頁面 {page_num+1}。")
continue
resized_watermark_pil = watermark_img_obj.resize((wm_width, wm_height), Image.LANCZOS)
# 調(diào)整水印圖片透明度
alpha = resized_watermark_pil.split()[-1]
alpha = Image.eval(alpha, lambda x: x * image_opacity)
resized_watermark_pil.putalpha(alpha)
# 將處理后的水印圖片轉(zhuǎn)為BytesIO,以便PyMuPDF插入
img_byte_arr = io.BytesIO()
resized_watermark_pil.save(img_byte_arr, format='PNG')
img_byte_arr_value = img_byte_arr.getvalue()
# 計(jì)算粘貼坐標(biāo)
insert_x, insert_y = 0, 0
if position == "top_left": insert_x, insert_y = 10, 10
elif position == "top_right": insert_x, insert_y = page_width - wm_width - 10, 10
elif position == "bottom_left": insert_x, insert_y = 10, page_height - wm_height - 10
elif position == "bottom_right": insert_x, insert_y = page_width - wm_width - 10, page_height - wm_height - 10
elif position == "center": insert_x, insert_y = (page_width - wm_width) // 2, (page_height - wm_height) // 2
insert_rect = fitz.Rect(insert_x, insert_y, insert_x + wm_width, insert_y + wm_height)
page.insert_image(insert_rect, stream=img_byte_arr_value, overlay=True)
print(f" - 頁面 {page_num+1} 已添加水印。")
doc.save(output_path)
print(f"? PDF水印添加完成!文件已保存到:'{output_path}'")
return True
finally:
if 'doc' in locals(): doc.close()
if 'watermark_img_obj' in locals(): watermark_img_obj.close() # 關(guān)閉水印圖片
if __name__ == "__main__":
# 準(zhǔn)備測試PDF文件 (多頁)
source_pdf_path = os.path.expanduser("~/Desktop/sample_report.pdf")
# 簡單創(chuàng)建模擬PDF文件
if not os.path.exists(source_pdf_path):
doc = fitz.open(); doc.new_page().insert_text(fitz.Point(50,50), "這是測試報告第一頁\n請勿復(fù)制"); doc.new_page().insert_text(fitz.Point(50,50), "這是第二頁"); doc.save(source_pdf_path); doc.close()
# 準(zhǔn)備Logo圖片 (如果測試圖片水印)
logo_path = os.path.expanduser("~/Desktop/company_logo.png")
if not os.path.exists(logo_path):
Image.new('RGBA', (100, 50), color = (255, 0, 0, 128)).save(logo_path) # 模擬透明紅色Logo
print(f"臨時Logo文件 '{os.path.basename(logo_path)}' 已創(chuàng)建。")
output_text_wm_pdf = os.path.expanduser("~/Desktop/report_with_text_wm.pdf")
output_image_wm_pdf = os.path.expanduser("~/Desktop/report_with_logo_wm.pdf")
# 示例1:批量添加文字水印
print("\n--- 示例1:添加文字水印 ---")
add_pdf_watermark(
source_pdf_path,
output_text_wm_pdf,
watermark_type="text",
text_content="【機(jī)密文件 嚴(yán)禁外傳】",
font_size=20, # 調(diào)整字體大小
text_color=(1, 0, 0), # 紅色 (0.0-1.0)
position="center" # 居中
)
# 示例2:批量添加圖片水印 (Logo)
print("\n--- 示例2:添加圖片Logo水印 ---")
add_pdf_watermark(
source_pdf_path,
output_image_wm_pdf,
watermark_type="image",
image_watermark_path=logo_path,
image_opacity=0.3, # 更透明
image_size_ratio=0.2 # 尺寸更大
)
操作:
安裝庫: pip install PyMuPDF Pillow。
準(zhǔn)備PDF和Logo: 在桌面創(chuàng)建sample_report.pdf(多頁),以及company_logo.png(一個Logo圖)。
修改代碼路徑和水印參數(shù): 修改 source_pdf_path、logo_path 等路徑和水印參數(shù)。
運(yùn)行: 運(yùn)行 python add_pdf_watermark.py。
注意中文: 如果使用中文水印,需要確保 CHINESE_FONT_PATH 指向一個存在的中文字體文件,否則可能顯示方塊。
展示:

3.2 批量添加頁碼:讓你的報告規(guī)范專業(yè)
場景: 制作長篇報告、書籍時,需要為每一頁自動添加統(tǒng)一的頁眉、頁腳和頁碼,如“第X頁 / 共Y頁”。手動在PDF編輯器中添加,效率極低且容易出錯。
方案: PyMuPDF能夠讓你自動化地為PDF文檔添加頁碼,讓你的文檔瞬間變得專業(yè)和規(guī)范。
代碼:
mport fitz # PyMuPDF
import os
# 確保中文字體路徑正確,用于PDF中文頁碼渲染
CHINESE_FONT_PATH = "C:/Windows/Fonts/simhei.ttf" # Windows黑體示例
def add_page_numbers_to_pdf(input_pdf_path, output_pdf_path, position="bottom_center", font_size=9, color=(0,0,0)):
"""
為PDF文件的每一頁批量添加頁碼。
這是Python處理PDF和PDF頁碼自動化的核心功能。
:param input_pdf_path: 源PDF文件路徑
:param output_pdf_path: 添加頁碼后PDF文件的輸出路徑
:param position: 頁碼位置 ("top_left", "top_right", "bottom_left", "bottom_right", "center", "bottom_center", "top_center")
:param font_size: 字體大小
:param color: 顏色 (R, G, B),范圍0.0-1.0
"""
if not os.path.exists(input_pdf_path): return print(f"? PDF文件不存在:{input_pdf_path}")
os.makedirs(os.path.dirname(output_pdf_path), exist_ok=True)
print(f"?? 正在為 '{os.path.basename(input_pdf_path)}' 批量添加頁碼...")
try:
doc = fitz.open(input_pdf_path)
# 嘗試加載中文字體 (用于中文頁碼,如“第X頁”)
font_name_in_pdf = "helv" # 默認(rèn)內(nèi)置字體 (英文數(shù)字)
if CHINESE_FONT_PATH and os.path.exists(CHINESE_FONT_PATH):
try:
doc.register_font(fontfile=CHINESE_FONT_PATH, fontname="MyCustomFont")
font_name_in_pdf = "MyCustomFont"
print(f" ?? 已注冊自定義字體 '{font_name_in_pdf}'。")
except Exception as e:
print(f"?? 注冊中文字體失?。簕e}。中文頁碼可能無法正確顯示。")
total_pages = doc.page_count
for page_num in range(total_pages):
page = doc.load_page(page_num)
# 頁碼文本:例如 "Page 1 / 10" 或 "第1頁 / 共10頁" (根據(jù)是否成功加載中文顯示)
page_text = f"Page {page_num + 1} / {total_pages}"
if font_name_in_pdf == "MyCustomFont": # 如果成功加載了中文字體
page_text = f"第 {page_num + 1} 頁 / 共 {total_pages} 頁"
# 計(jì)算頁碼位置
rect = page.rect # 頁面矩形
# fitz.Font().text_bbox() 更精確計(jì)算文本寬度,這里使用估算
# text_len_estimate = fitz.Font(fontname=font_name_in_pdf).text_bbox(page_text, fontsize=font_size)[2]
text_len_estimate = font_size * len(page_text) * 0.6 # 粗略估算寬度
text_height_estimate = font_size * 1.2 # 粗略估算高度
x, y = 0, 0
if position == "top_left": x, y = rect.x0 + 20, rect.y0 + 20
elif position == "top_right": x, y = rect.x1 - text_len_estimate - 20, rect.y0 + 20
elif position == "bottom_left": x, y = rect.x0 + 20, rect.y1 - text_height_estimate - 20
elif position == "bottom_right": x, y = rect.x1 - text_len_estimate - 20, rect.y1 - text_height_estimate - 20
elif position == "center": x, y = (rect.width - text_len_estimate) / 2, (rect.height - text_height_estimate) / 2
elif position == "bottom_center": x, y = (rect.width - text_len_estimate) / 2, rect.y1 - text_height_estimate - 20
elif position == "top_center": x, y = (rect.width - text_len_estimate) / 2, rect.y0 + 20
page.insert_text(
(x, y),
page_text,
fontname=font_name_in_pdf, # 使用注冊的字體名或內(nèi)置字體
fontsize=font_size,
color=color, # 顏色 (R, G, B) 范圍0.0-1.0
overlay=True # 確保頁碼在內(nèi)容之上
)
print(f" - 頁面 {page_num+1} 已添加頁碼。")
doc.save(output_path)
print(f"? PDF頁碼添加完成!文件已保存到:'{output_path}'")
return True
finally:
if 'doc' in locals(): doc.close()
if __name__ == "__main__":
input_pdf = os.path.expanduser("~/Desktop/long_report_no_pages.pdf")
output_pdf = os.path.expanduser("~/Desktop/report_with_page_numbers.pdf")
# 簡單創(chuàng)建模擬PDF文件 (多頁)
if not os.path.exists(input_pdf):
doc = fitz.open()
for i in range(5):
page = doc.new_page()
page.insert_text(fitz.Point(50,50), f"這是第 {i+1} 頁的內(nèi)容。")
doc.save(input_pdf); doc.close()
# 示例1:添加右下角居中頁碼
print("\n--- 示例1:添加居中底部頁碼 ---")
add_page_numbers_to_pdf(
input_pdf,
output_pdf,
position="bottom_center",
font_size=10,
color=(0, 0, 0) # 黑色
)
操作步驟:
安裝PyMuPDF: pip install PyMuPDF。
準(zhǔn)備PDF文件: 在桌面準(zhǔn)備一個包含多頁的PDF文件(如long_report_no_pages.pdf)。
修改代碼路徑和頁碼參數(shù): 修改 input_pdf 和 output_pdf。
運(yùn)行: 運(yùn)行 python add_pdf_page_numbers.py。
效果展示:

3.3 PDF密碼加密與解密:為你的重要文檔上鎖
場景: 你的PDF報告或合同包含敏感信息,需要進(jìn)行PDF加密保護(hù),只有擁有密碼的人才能打開。手動設(shè)置密碼繁瑣且不安全。
方案: PyPDF2能夠?qū)崿F(xiàn)PDF文件的密碼加密和解密,為你的敏感文檔加上一把“安全鎖”,確保PDF加密和PDF解密的便捷。
代碼:
from PyPDF2 import PdfReader, PdfWriter
import os
import shutil # 用于復(fù)制文件,如果未加密則直接復(fù)制
def encrypt_pdf_with_password(pdf_path, output_path, password):
"""
使用密碼加密PDF文件。
這是PDF自動化和PDF加密的核心功能。
:param pdf_path: 源PDF文件路徑
:param output_path: 加密后PDF文件的輸出路徑
:param password: 加密密碼 (字符串)
"""
if not os.path.exists(pdf_path): return print(f"? PDF文件不存在:{pdf_path}")
os.makedirs(os.path.dirname(output_path), exist_ok=True)
reader = PdfReader(pdf_path)
writer = PdfWriter()
print(f"?? 正在加密PDF文件 '{os.path.basename(pdf_path)}'...")
for page in reader.pages:
writer.add_page(page) # 將所有頁面添加到writer
try:
writer.encrypt(password) # 設(shè)置加密密碼
with open(output_path, "wb") as output_pdf_file:
writer.write(output_pdf_file)
print(f"? PDF文件加密成功!保存到:'{output_path}'")
return True
except Exception as e:
print(f"? PDF加密失?。簕e}")
return False
def decrypt_pdf_with_password(encrypted_pdf_path, output_path, password):
"""
使用密碼解密PDF文件。
這是PDF自動化和PDF解密的核心功能。
:param encrypted_pdf_path: 加密PDF文件路徑
:param output_path: 解密后PDF文件的輸出路徑
:param password: 解密密碼 (字符串)
"""
if not os.path.exists(encrypted_pdf_path): return print(f"? 加密PDF文件不存在:{encrypted_pdf_path}")
os.makedirs(os.path.dirname(output_path), exist_ok=True)
reader = PdfReader(encrypted_pdf_path)
if reader.is_encrypted:
if not reader.decrypt(password): # 嘗試解密
print(f"? 解密失?。?{os.path.basename(encrypted_pdf_path)}' 密碼不正確或文件已損壞。")
return False
else:
print(f"?? 文件 '{os.path.basename(encrypted_pdf_path)}' 未加密,直接復(fù)制到輸出路徑。")
shutil.copyfile(encrypted_pdf_path, output_path) # 未加密則直接復(fù)制
print(f"文件已直接復(fù)制到:'{output_path}'")
return True
writer = PdfWriter()
for page in reader.pages:
writer.add_page(page)
try:
with open(output_path, "wb") as output_pdf_file:
writer.write(output_pdf_file)
print(f"? PDF文件解密成功!保存到:'{output_path}'")
return True
except Exception as e:
print(f"? PDF解密失敗:{e}")
return False
if __name__ == "__main__":
# 準(zhǔn)備測試PDF文件
source_pdf = os.path.expanduser("~/Desktop/secret_document.pdf")
if not os.path.exists(source_pdf):
doc = fitz.open(); doc.new_page().insert_text(fitz.Point(50,50), "這是機(jī)密文檔"); doc.save(source_pdf); doc.close()
encrypted_pdf = os.path.expanduser("~/Desktop/secret_document_encrypted.pdf")
decrypted_pdf = os.path.expanduser("~/Desktop/secret_document_decrypted.pdf")
password = "MySecurePassword123"
# 示例1:加密PDF
print("\n--- 示例1:加密PDF文件 ---")
encrypt_pdf_with_password(source_pdf, encrypted_pdf, password)
# 示例2:解密PDF
print("\n--- 示例2:解密PDF文件 ---")
decrypt_pdf_with_password(encrypted_pdf, decrypted_pdf, password)
# 示例3:嘗試用錯誤密碼解密
print("\n--- 示例3:嘗試用錯誤密碼解密 ---")
decrypt_pdf_with_password(encrypted_pdf, os.path.expanduser("~/Desktop/failed_decryption.pdf"), "WrongPassword")
步驟:
安裝庫: pip install PyPDF2 PyMuPDF (PyMuPDF用于創(chuàng)建測試PDF)。
準(zhǔn)備PDF: 在桌面創(chuàng)建secret_document.pdf。
修改代碼路徑和密碼: 修改 source_pdf 等路徑和 password。
運(yùn)行: 運(yùn)行 python pdf_encrypt_decrypt.py。
效果展示:

4. 階段性總結(jié)pdf 全能管家
通過本篇文章,你已經(jīng)掌握了PDF文檔自動化的各項(xiàng)核心魔法,親手打造了一個能夠一鍵合并、分割、水印、提取與加密解密的 PDF全能管家!
我們深入學(xué)習(xí)了PyPDF2和PyMuPDF等庫,它們堪稱Python PDF庫中的“瑞士軍刀”,實(shí)現(xiàn)了:
PDF合并分割: 輕松將多份PDF批量合并,或?qū)㈤L篇PDF按頁分割,高效整理文檔。
PDF水?。?自動化添加文字/圖片Logo水印,保護(hù)文檔版權(quán),提升專業(yè)度。
PDF頁碼自動化: 告別手動排版,為報告批量加頁碼,瞬間規(guī)范。
PDF加密解密: 為你的敏感PDF文件加把“安全鎖”,確保文檔管理中的數(shù)據(jù)安全。
現(xiàn)在,你不再需要為PDF文件難管理、編輯受限、手動操作低效而煩惱。
5.尾聲:PDF自動化,解鎖文檔管理新高度!
通過本篇文章,你已經(jīng)掌握了PDF文檔自動化的強(qiáng)大能力,為你的辦公自動化之旅又增添了一個重量級技能!你學(xué)會了如何利用Python的PDF處理庫,高效地進(jìn)行PDF文檔的合并、分割、水印、頁碼和加密解密。

除了今天學(xué)到的PDF自動化功能,你還希望Python能幫你實(shí)現(xiàn)哪些更復(fù)雜的PDF處理需求?比如:自動填寫PDF表單?將PDF內(nèi)容智能轉(zhuǎn)換為Excel或Word?
以上就是使用Python實(shí)現(xiàn)PDF文檔自動化的操作大全(一鍵合并、分割、水印、提取與加密解密)的詳細(xì)內(nèi)容,更多關(guān)于Python PDF文檔自動化的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用Python實(shí)現(xiàn)Windows系統(tǒng)垃圾清理
Windows自帶的磁盤清理工具功能有限,無法深度清理各類垃圾文件,所以本文為大家介紹了如何使用Python+PyQt5開發(fā)一個Windows系統(tǒng)垃圾清理神器吧2025-05-05
Python寫的創(chuàng)建文件夾自定義函數(shù)mkdir()
這篇文章主要介紹了Python寫的創(chuàng)建文件夾自定義函數(shù)mkdir(),文件夾操作是編程中經(jīng)常需要的,mkdir函數(shù)更是經(jīng)典中的經(jīng)典,需要的朋友可以參考下2014-08-08
Anaconda環(huán)境中conda與pip命令的區(qū)別小結(jié)
本文主要介紹了Anaconda環(huán)境中conda與pip命令的區(qū)別小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-05-05

