Python操作PDF-文本和圖片提取(使用PyPDF2和PyMuPDF)


PDF文件格式

如今,可移植文檔格式(PDF)屬於最常用的數據格式。在1990年,PDF文檔的結構由Adobe定義。PDF格式的思想是,對於通信過程中涉及的雙方(創建者,作者或發送者以及接收者)而言,傳輸的數據/文檔看起來完全相同。

工具和庫

適用於Python的PDF工具,模塊和庫的可用解決方案范圍有些混亂,需要花一點時間弄清楚什么是什么,以及哪些項目需要連續維護。根據我們的研究,以下是最新的候選人:

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

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

  • pdflib for Python:Poppler庫的擴展,為它提供了Python綁定。它使您可以解析,分析和轉換PDF文檔。不要將其與具有相同名稱的商業吊墜相混淆。

  • PyFPDF:一個在Python下生成PDF文檔的庫。從FPDF PHP庫移植而來,這是著名的PDFlib擴展替換,其中包含許多示例,腳本和派生類。

  • PDFTables:一項商業服務,提供從PDF文檔附帶的表格中提取的內容。提供一個API,以便PDFTables可以用作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的一部分。

圖書館 用於
PyPDF2
PyMuPDF
pdflib
PDF表格
PDFMiner.six
PDF查詢
pdfrw 讀,寫/創作
PyFPDF 寫/創作

我們將重點介紹PyPDF2和PyMuPDF,並說明如何以最簡單的方式提取文本和圖像。為了了解PyPDF2的用法,官方文檔和許多其他資源提供的示例的組合對您有所幫助。相比之下,官方PyMuPDF文檔更加清晰,並且使用該庫的速度也大大加快。

使用PyPDF2提取文本

$ pip3 install PyPDF2

清單1首先導入了PdfFileReader該類。接下來,使用該類打開文檔,並使用getDocumentInfo()方法提取文檔信息,使用提取頁數getDocumentInfo()以及第一頁的內容。

請注意,PyPDF2從0開始計數頁面,這就是該調用pdf.getPage(0)檢索文檔第一頁的原因。最終,提取的信息被打印到stdout

清單1:提取文檔信息和內容。

#!/usr/bin/python

from PyPDF2 import PdfFileReader

pdf_document = "example.pdf"
with open(pdf_document, "rb") as filehandle:
    pdf = PdfFileReader(filehandle)
    info = pdf.getDocumentInfo()
    pages = pdf.getNumPages()

    print (info)
    print ("number of pages: %i" % pages)

    page1 = pdf.getPage(0)
    print(page1)
    print(page1.extractText())

如上面的圖1所示,提取的文本是連續打印的。沒有段落或句子分隔。如PyPDF2文檔中所述,所有文本數據都按照在頁面內容流中提供的順序返回,並且依靠它可能會導致一些意外。這主要取決於PDF文檔的內部結構,以及PDF編寫器過程如何生成PDF指令流。

使用PyMuPDF提取文本

可從PyPi網站上獲取PyMuPDF,並在終端中使用以下命令安裝軟件包:

$ pip3 install PyMuPDF

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

清單2:使用PyMuPDF從PDF文檔中提取內容。

#!/usr/bin/python

import fitz

pdf_document = "example.pdf"
doc = fitz.open(pdf_document)
print ("number of pages: %i" % doc.pageCount)
print(doc.metadata)

page1 = doc.loadPage(0)
page1text = page1.getText("text")
print(page1text)

PyMuPDF的優點是可以保持原始文檔結構完整-帶有換行符的整個段落都保留在PDF文檔中(參見圖2)。

使用PyMuPDF從PDF提取圖像

PyMuPDF使用該方法簡化了從PDF文檔提取圖像的過程getPageImageList()清單3基於PyMuPDF Wiki頁面上的示例,並逐頁地將PDF中的所有圖像提取並保存為PNG文件。如果圖像具有CMYK色彩空間,則將首先將其轉換為RGB。

清單3:提取圖像

#!/usr/bin/python

import fitz

pdf_document = fitz.open("file.pdf")
for current_page in range(len(pdf_document)):
    for image in pdf_document.getPageImageList(current_page):
        xref = image[0]
        pix = fitz.Pixmap(pdf_document, xref)
        if pix.n < 5:        # this is GRAY or RGB
            pix.writePNG("page%s-%s.png" % (current_page, xref))
        else:                # CMYK: convert to RGB first
            pix1 = fitz.Pixmap(fitz.csRGB, pix)
            pix1.writePNG("page%s-%s.png" % (current_page, xref))
            pix1 = None
        pix = None

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

圖3:提取的圖像

使用PyPDF2將PDF拆分為頁面

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

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

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

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

清單4:將PDF拆分為單個頁面。

#!/usr/bin/python

from PyPDF2 import PdfFileReader, PdfFileWriter

pdf_document = "example.pdf"
pdf = PdfFileReader(pdf_document)

for page in range(pdf.getNumPages()):
    pdf_writer = PdfFileWriter()
    current_page = pdf.getPage(page)
    pdf_writer.addPage(current_page)

    outputFilename = "example-page-{}.pdf".format(page + 1)
    with open(outputFilename, "wb") as out:
        pdf_writer.write(out)

        print("created", outputFilename)

查找所有包含文本的頁面

這個用例非常實用,並且工作方式類似於pdfgrep。該腳本使用PyMuPDF返回包含給定搜索字符串的所有頁碼。頁面一頁接一頁地加載,借助該searchFor()方法,將檢測到搜索字符串的所有出現情況。如果匹配則在上面印有相應的信息stdout

清單5:搜索給定的文本。

#!/usr/bin/python

import fitz

filename = "example.pdf"
search_term = "invoice"
pdf_document = fitz.open(filename):

for current_page in range(len(pdf_document)):
    page = pdf_document.loadPage(current_page)
    if page.searchFor(search_term):
        print("%s found on page %i" % (search_term, current_page))

下面的圖5顯示了一本400頁的書中“ Debian GNU / Linux”一詞的搜索結果。

結論

此處顯示的處理PDF方法非常強大。使用相對較少的代碼行數,很容易獲得結果。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM