公司船務(wù)部一個重要任務(wù)就是需要準(zhǔn)備每單貨物的發(fā)票,從系統(tǒng)導(dǎo)出發(fā)票時是默認(rèn)存為一個PDF文檔,在打印的時候,有多少個文件,就需要點(diǎn)多少次“打印”。如果能夠?qū)?dāng)天的發(fā)票PDF檔合并在一個PDF里面,只需要點(diǎn)一次“打印”即可完成。 在網(wǎng)上我們可以搜到很多PDF合并軟件,但在真實(shí)工作環(huán)境下并不是非常實(shí)用,比如有些PDF有封面頁,我們在合并的時候只需要第一個文件的封面即可,后續(xù)的只要封面后的內(nèi)容。而PDF合并軟件是簡單粗暴的直接將所有內(nèi)容合并,那合并后的文件就會多出很多我們不需要的“封面”。 Python有一個庫PyPDF2 可輕松解決這個小問題,可以實(shí)現(xiàn)任意選定頁面的合并。通過文件夾遍歷,可以將不同文件夾下的PDF按選定的頁面合并在一起,方便實(shí)用,絕不含糊。 %%time import PyPDF2 #可從PDF文檔提取信息 import os #用于獲取需要合并的PDF文件所在路徑 path='data/' # 文件夾路徑 #1.獲取需要用于合并的文件名及路徑 files=[] for file in os.listdir(path): if file.endswith('.pdf'): #排除文件夾內(nèi)的其它干擾文件,只獲取PDF文件 files.append(path+file) #2.獲取每個PDF文件里面需要的信息并添加到寫入文件 pdf_writer=PyPDF2.PdfFileWriter() for file in files: pdf_obj=open(file,'rb')# 以二進(jìn)制讀取,將保留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('data\combined_inv.pdf','wb') #以二進(jìn)制寫入,將保留源PDF中的所有信息 pdf_writer.write(pdf_output_file) pdf_output_file.close()
我們先導(dǎo)入PyPDF2 和os 庫。若未安裝PyPDF2 ,可運(yùn)行'cmd.exe',輸入'pip install PyPDF2',請注意PyPDF2有大小寫要求,不然無法安裝。 然后定義pyth為我們需要操作的文件夾的路徑。隨后就需要獲取我們待合并的所有PDF文件的文件名和路徑,并存入我們定義的列表files 。如果文件夾內(nèi)有非pdf文件,也會被獲取。比如如下,我們可以看到這個路徑下有一個txt文件,那可不是我們想要的。因此需要加入一個篩選,file.endswith('.pdf') 我們只要以'.pdf'結(jié)尾的文件。這樣得到的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的操作要求,我們需要按如下步驟來進(jìn)行讀取和寫入: 1. 打開PDF文件,得到一個“讀取”對象。讀取對象相當(dāng)于是盛裝這個PDF文件內(nèi)容的容器。 2.創(chuàng)建一個 “寫入” 對象,相當(dāng)于另一個容器,用于向其中轉(zhuǎn)移上一個步驟讀取出來的內(nèi)容。 3.將頁面從 “讀取” 容器倒入 “寫入” 容器之中。 4.待“寫入”容器裝完所有需要的內(nèi)容后,寫入并輸出新的 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代表第二頁?!皃df_reader.numPages”是該P(yáng)DF文件的總頁數(shù)。pdf_reader.getPage(page_num) 可獲得其中每頁的信息,我們將它存入page_obj 容器。隨后我們使用addPage方法pdf_writer.addPage(page_obj) 將page_obj 中的信息放入最開始的pdf_writer容器中。
就這樣逐個打開相關(guān)PDF文件,讀取文件,獲取頁面信息,然后存入pdf_writer容器。如同吃火鍋時,從不同的佐料中取我們想要的佐料和量,加入到自己的油碟中一樣。 待所有想要合并的頁面都加入pdf_writer容器之后,就可以寫入新的PDF文件并保存了。先新建一個名為“combined_inv.pdf”的文件,并以二進(jìn)制打開 open('data\combined_inv.pdf','wb') 。然后將pdf_writer容器中的所有信息用write方法寫入到新的文件pdf_writer.write(pdf_output_file) 。最后關(guān)閉該文件pdf_output_file.close() ,操作完成。合并后的PDF文件combined_inv.pdf 如下:
所有源代碼和說明都在Jupyter notebook上完成,所用到的Excel 資料已上傳GitHub, 歡迎Fork或下載到本地隨意玩。。。轉(zhuǎn)載請注明出處,謝謝。 GitHub鏈接: https://github.com/weidylan/Office_Automation_by_Using_Python
|