程序員學習之在Python中使用PDF:閱讀、旋轉、合併和拆分

私信我或關注微信號:猿來如此呀,回覆:學習,獲取免費學習資源包。

PDF 文檔格式

今天,可移植文檔格式(PDF)屬於最常用的數據格式。 1990年,Adobe定義了PDF文檔格式。 PDF格式背後的想法是傳輸的數據/文檔對於通信過程中涉及的雙方——創建者,作者或發送者和接收者來說看起來完全相同。 PDF是PostScript格式的後續版本,標準化為ISO 32000-2:2017。

程序員學習之在Python中使用PDF:閱讀、旋轉、合併和拆分


處理PDF文檔

對於Linux,有很多可用的命令行工具,如pdftk和pdfgrep來操作pdf。 作為開發人員,您可以構建自己的基於Python的軟件,並使用免費提供的PDF庫。

本文是一個小系列的開頭,將介紹這些有用的Python庫。 在第一部分中,我們將重點介紹現有PDF的操作。 您將學習如何閱讀和提取內容(文本和圖像),旋轉單個頁面以及將文檔拆分為單獨的頁面。 第二部分將介紹如何根據疊加層添加水印。 第三部分將專注於編寫/創建PDF,還將包括刪除和重新組合單個頁面到新文檔。

工具和庫

Python相關的PDF工具,模塊和庫的可用解決方案範圍有點令人困惑,需要花一點時間來弄清楚什麼是什麼,以及哪些項目是持續維護的。 根據我們的研究,這些是目前最新的方案:

PyPDF2:這是一個Python庫,用於提取文檔信息和內容,逐頁拆分文檔,合併文檔,裁剪頁面和添加水印。 PyPDF2支持未加密和加密的文檔。

PDFMiner:完全用Python編寫,適用於Python 2.4。對於Python 3,請使用克隆包PDFMiner.six。這兩個包都允許您解析,分析和轉換PDF文檔。包括對PDF 1.7以及CJK語言(中文,日文和韓文)以及各種字體類型(Type1,TrueType,Type3和CID)的支持。

PDFQuery:它將自己描述為“一個快速且友好的PDF抓取庫”,它作為PDFMiner,lxml和pyquery的包裝器實現。它的設計目標是“用盡可能少的代碼可靠地從PDF集合中提取數據。”

tabula-py:它是tabula-java的簡單Python包裝器,可以從PDF中讀取表並將它們轉換為Pandas DataFrames。它還允許您將PDF文件轉換為CSV / TSV / JSON文件。

pdflib for Python:Poppler庫的擴展,為它提供Python綁定。它允許您解析,分析和轉換PDF文檔。不要與其同名的商業吊墜相混淆。

PyFPDF:用於在Python下生成PDF文檔的庫。從FPDF PHP庫移植,一個眾所周知的PDFlib擴展替換,包含許多示例,腳本和衍生產品。

PDFTables:一種商業服務,提供從PDF文檔中提取的表格。提供API以便PDFTable可以用作SAAS。

PyX - Python圖形包:PyX是一個用於創建PostScript,PDF和SVG文件的Python包。它結合了PostScript繪圖模型的抽象和TeX / LaTeX接口。這些基元構建了複雜的任務,例如以發佈就緒質量創建2D和3D圖。

ReportLab:一個雄心勃勃的工業級圖書館,主要致力於精確創建PDF文檔。可作為開源版本以及名為ReportLab PLUS的商業增強版本免費提供。

PyMuPDF(又名“fitz”):MuPDF的Python綁定,它是一個輕量級的PDF和XPS查看器。該庫可以訪問PDF,XPS,OpenXPS,epub,漫畫和小說書籍格式的文件,並以其頂級性能和高渲染質量而聞名。

pdfrw:一種基於Python的純PDF解析器,用於讀寫PDF。它忠實地再現了矢量格式而沒有光柵化。與ReportLab結合使用,有助於在使用ReportLab創建的新PDF中重複使用現有PDF的部分內容。

程序員學習之在Python中使用PDF:閱讀、旋轉、合併和拆分


下面我們將重點介紹PyPDF2和PyMuPDF,並解釋如何以最簡單的方式提取文本和圖像。 為了理解PyPDF2的用法,官方文檔和其他資源提供的大量示例的組合。 相比之下,官方的PyMuPDF文檔更清晰,使用庫的速度要快得多。

用PyPDF2提取文檔

PyPDF2可以作為常規軟件包安裝,也可以使用pip3(適用於Python3)安裝。 這裡的測試基於即將推出的Debian GNU / Linux版本10“Buster”的軟件包。 Debian軟件包的名稱是python3-pypdf2。

下面的代碼首先導入PdfFileReader 類,然後適用這個類打開文件,用getDocumentInfo() 方法來提取文檔信息,包括頁數和首頁內容。

請注意PyPDF2頁碼計數從0開始,這也是為什麼pdf.getPage(0) 函數可以獲取文件的第一頁。最終,提取到的信息被打印到了stdout。

程序員學習之在Python中使用PDF:閱讀、旋轉、合併和拆分


使用PyMuPDF提取文本

PyMuPDF可從PyPi網站獲得,您可以在終端中使用以下命令安裝包:

程序員學習之在Python中使用PDF:閱讀、旋轉、合併和拆分


顯示文檔信息,打印頁數和提取PDF文檔的文本的方式與PyPDF2類似(參見清單2)。 要導入的模塊名為fitz,並返回到PyMuPDF的先前名稱。

程序員學習之在Python中使用PDF:閱讀、旋轉、合併和拆分


PyMuPDF的優點在於它保持原始文檔結構的完整性 - 帶有換行符的整個段落保留在PDF文檔中。

使用PyMuPDF從PDF中提取圖像

PyMuPDF使用getPageImageList()方法簡化了從PDF文檔中提取圖像的過程。下面的代碼來源於PyMuPDF wiki頁面的示例,並逐頁提取並保存PDF中的所有圖像作為PNG文件。 如果圖像具有CMYK顏色空間,則首先將其轉換為RGB。

程序員學習之在Python中使用PDF:閱讀、旋轉、合併和拆分


在400頁PDF上運行這個Python腳本,它在不到3秒的時間內提取了117個圖像,這是驚人的。 各個圖像以PNG格式存儲。 為了保持原始圖像格式和大小,而不是轉換為PNG,請查看PyMuPDF wiki中腳本的擴展版本。

如何旋轉頁面?

有時候PDF是橫向模式而不是縱向模式,甚至是顛倒的。當有人掃描文檔為PDF或電子郵件時,很可能會發生這種情況。我們可以打印出文檔並閱讀紙質版本,也可以使用Python的強大功能來旋轉有問題的頁面。

下面看一下如何使用PyPDF2旋轉文章的一些頁面:

from PyPDF2 import PdfFileReader, PdfFileWriter
def rotate_pages(pdf_path):
pdf_writer = PdfFileWriter()
pdf_reader = PdfFileReader(path)
# 順時針旋轉90度
page_1 = pdf_reader.getPage(0).rotateClockwise(90)
pdf_writer.addPage(page_1)
# 逆時針旋轉90度
page_2 = pdf_reader.getPage(1).rotateCounterClockwise(90)
pdf_writer.addPage(page_2)
# 在正常方向上添加一頁
pdf_writer.addPage(pdf_reader.getPage(2))
with open('rotate_pages.pdf', 'wb') as fh:
pdf_writer.write(fh)
if __name__ == '__main__':
path = '新路徑.pdf'
rotate_pages(path)


上面除了pdfileReader之外,還導入了pdfileWriter,因為我們需要編寫一個新的pdf。rotate_pages()獲取要修改的PDF的路徑。在這個函數中,需要創建一個可以命名為pdf-writer的writer對象和一個名為pdf-reader的reader對象。

接下來,可以使用.get page()獲取所需的頁面。上面開始輸入了第0頁,也就是第一頁,調用page對象的.rotateClockwise()順時針旋轉方法並輸入90。然後同樣地,對於第二頁,調用.rotateCounterLockwise()逆時針旋轉並輸入90。

每次調用Rotation旋轉方法後,都會調用.addPage(),這將向writer對象添加頁面的旋轉版本。最後一頁是第3頁,沒有對其進行任何旋轉。最後,使用.write()把所有新頁寫入新的PDF。


使用PyPDF2將PDF拆分為頁面

對於此示例,首先需要導入PdfFileReader和PdfFileWriter類。 然後我們打開PDF文件,創建一個reader對象,並使用reader對象的getNumPages方法遍歷所有頁面。

在for循環中,我們創建了一個新的PdfFileWriter實例,它不包含任何頁面。 然後,我們使用pdfWriter.addPage()方法將當前頁面添加到writer對象。 此方法接受頁面對象,我們使用PdfFileReader.getPage()方法獲取該頁面對象。

下一步是創建一個唯一的文件名,我們使用原始文件名加上“page”一詞加上頁碼。 我們在當前頁碼中加1,因為PyPDF2計算從零開始的頁碼。

最後,我們以“write binary”模式(模式wb)打開新文件名,並使用pdfWriter類的write()方法將提取的頁面保存到磁盤。

程序員學習之在Python中使用PDF:閱讀、旋轉、合併和拆分

如何合併PDF?


在許多情況下,我們希望將兩個或多個PDF合併到一個PDF中。例如,現在可能有一個標準的封面,需要轉到許多類型的報告中。這時候就可以使用python來幫助完成這類工作。

下面是實現的代碼,完成PDF合併的操作:

from PyPDF2 import PdfFileReader, PdfFileWriter
def merge_pdfs(paths, output):
pdf_writer = PdfFileWriter()
for path in paths:
pdf_reader = PdfFileReader(path)
for page in range(pdf_reader.getNumPages()):
# 將每頁添加到writer對象
pdf_writer.addPage(pdf_reader.getPage(page))
# 寫入合併的pdf
with open(output, 'wb') as out:
pdf_writer.write(out)
if __name__ == '__main__':
paths = ['document1.pdf', 'document2.pdf']
merge_pdfs(paths, output='merged.pdf')

假如有一個要合併到一起的pdf列表時,可以直接使用merge_pdf函數完成。此函數採用了輸入路徑和輸出路徑作為參數。

首先遍歷輸入的paths,併為每個輸入創建一個PDF閱讀對象。然後遍歷PDF文件中的所有頁面,並使用.addpage()將這些頁面寫入writer對象。當完成對列表中所有PDF的所有頁面的寫入後,將在末尾寫入新的結果中。

如果不想合併每個PDF的所有頁面,可以通過添加一系列要添加的頁面來稍微增強這個腳本。挑戰一點的話,也可以使用Python的argparse模塊為這個函數創建一個命令行接口。


查找包含文本的所有頁面

這個功能非常實用,與pdfgrep類似。 使用PyMuPDF,腳本將返回包含給定搜索字符串的所有頁碼。 頁面一個接一個地加載,並且在searchFor()方法的幫助下,檢測到搜索字符串的所有出現。 如果匹配,則在stdout上打印相應的消息。

程序員學習之在Python中使用PDF:閱讀、旋轉、合併和拆分


結論:

這裡講解的方法非常強大。 使用相對較少數量的代碼行,可以輕鬆獲得結果。


分享到:


相關文章: