實例4:用Python提取不同PDF文件中的頁面合併進新的PDF文件

公司船務部一個重要任務就是需要準備每單貨物的發票,從系統導出發票時是默認存為一個PDF文檔,在列印的時候,有多少個文件,就需要點多少次「列印」。如果能夠將當天的發票PDF檔合併在一個PDF裡面,只需要點一次「列印」即可完成。

在網上我們可以搜到很多PDF合併軟體,但在真實工作環境下並不是非常實用,比如有些PDF有封面頁,我們在合併的時候只需要第一個文件的封面即可,後續的只要封面後的內容。而PDF合併軟體是簡單粗暴的直接將所有內容合併,那合併後的文件就會多出很多我們不需要的「封面」。

Python有一個庫PyPDF2可輕鬆解決這個小問題,可以實現任意選定頁面的合併。通過文件夾遍歷,可以將不同文件夾下的PDF按選定的頁面合併在一起,方便實用,毫不含糊。

%%time
import PyPDF2 #可從PDF文檔提取信息
import os #用於獲取需要合併的PDF文件所在路徑
path="data/" # 文件夾路徑
#1.獲取需要用於合併的文件名及路徑
files=[]
for file in os.listdir(path):
if file.endswith(".pdf"): #排除文件夾內的其它干擾文件,只獲取PDF文件
files.append(path+file)
#2.獲取每個PDF文件裡面需要的信息並添加到寫入文件
pdf_writer=PyPDF2.PdfFileWriter()
for file in files:
pdf_obj=open(file,rb)# 以二進位讀取,將保留PDF中的所有信息
pdf_reader=PyPDF2.PdfFileReader(pdf_obj)
for page_num in range(1,pdf_reader.numPages): #不要第一頁的封面,從第2頁開始獲取
page_obj=pdf_reader.getPage(page_num)
pdf_writer.addPage(page_obj)
#3.寫入並保存匯總PDF文件
pdf_output_file=open("datacombined_inv.pdf",wb) #以二進位寫入,將保留源PDF中的所有信息
pdf_writer.write(pdf_output_file)
pdf_output_file.close()

我們先導入PyPDF2os庫。若未安裝PyPDF2,可運行"cmd.exe",輸入"pip install PyPDF2",請注意PyPDF2有大小寫要求,不然無法安裝。

然後定義pyth為我們需要操作的文件夾的路徑。隨後就需要獲取我們待合併的所有PDF文件的文件名和路徑,並存入我們定義的列表files。如果文件夾內有非pdf文件,也會被獲取。比如如下,我們可以看到這個路徑下有一個txt文件,那可不是我們想要的。因此需要加入一個篩選,file.endswith(".pdf")我們只要以".pdf"結尾的文件。這樣得到的files列表就是我們需要合併的文件及其路徑了。files.append(path+file)裡面"path+file"是用於將路徑和文件名連接起來,這樣才能得到文件的完整路徑,程序才可以找得到這個文件。

os.listdir(path)
>[combined_inv.pdf,
INV1.pdf,
INV2.pdf,
INV3.pdf,
INV4.pdf,
INV5.pdf,
test.txt]

files
>[data/INV1.pdf,
data/INV2.pdf,
data/INV3.pdf,
data/INV4.pdf,
data/INV5.pdf]

待合併的PDF文件路徑搜集完後,就可以開始逐個讀取其中想要的頁面了。按照PyPDF2的操作要求,我們需要按如下步驟來進行讀取和寫入:

1. 打開PDF文件,得到一個「讀取」對象。讀取對象相當於是盛裝這個PDF文件內容的容器。

2.創建一個 「寫入」 對象,相當於另一個容器,用於向其中轉移上一個步驟讀取出來的內容。

3.將頁面從 「讀取」 容器倒入 「寫入」 容器之中。

4.待「寫入」容器裝完所有需要的內容後,寫入並輸出新的 PDF。

pdf_writer=PyPDF2.PdfFileWriter()就是用於裝待寫入文件的容器, PyPDF2.PdfFileWriter()是固定寫法,其原理就無需深究了。然後我們讀取每個PDF文件,先將打開PDF文件,並存到pdf_obj,然後使用PyPDF2.PdfFileReader(pdf_obj)讀取其中的信息,存到pdf_reader,然後再獲取其中的頁面,此處我們將其中第2頁及以後的頁(如果有的話)面提取出來。因此range(1,pdf_reader.numPages)是從1開始,因為range是從0索引開始,因此1代表第二頁。「pdf_reader.numPages」是該PDF文件的總頁數。pdf_reader.getPage(page_num)可獲得其中每頁的信息,我們將它存入page_obj容器。隨後我們使用addPage方法pdf_writer.addPage(page_obj)page_obj中的信息放入最開始的pdf_writer容器中。

就這樣逐個打開相關PDF文件,讀取文件,獲取頁面信息,然後存入pdf_writer容器。如同吃火鍋時,從不同的佐料中取我們想要的佐料和量,加入到自己的油碟中一樣。

待所有想要合併的頁面都加入pdf_writer容器之後,就可以寫入新的PDF文件並保存了。先新建一個名為「combined_inv.pdf」的文件,並以二進位打開 open("datacombined_inv.pdf",wb)。然後將pdf_writer容器中的所有信息用write方法寫入到新的文件pdf_writer.write(pdf_output_file)。最後關閉該文件pdf_output_file.close(),操作完成。合併後的PDF文件combined_inv.pdf如下:

所有源代碼和說明都在Jupyter notebook上完成,所用到的Excel 資料已上傳GitHub, 歡迎Fork或下載到本地隨意玩。。。轉載請註明出處,謝謝。

GitHub鏈接:github.com/weidylan/Off

微信公眾號:Python操作EXCEL高效率工作


推薦閱讀:

TAG:PDF | Python | Python開發 |