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

PDF文件格式

如今凌节,可移植文檔格式(PDF)屬于最常用的數(shù)據(jù)格式。在1990年洒试,PDF文檔的結(jié)構(gòu)由Adobe定義倍奢。PDF格式的思想是,對于通信過程中涉及的雙方(創(chuàng)建者垒棋,作者或發(fā)送者以及接收者)而言卒煞,傳輸?shù)臄?shù)據(jù)/文檔看起來完全相同。

工具和庫

適用于Python的PDF工具叼架,模塊和庫的可用解決方案范圍有些混亂畔裕,需要花一點時間弄清楚什么是什么,以及哪些項目需要連續(xù)維護乖订。根據(jù)我們的研究扮饶,以下是最新的候選人:

  • PyPDF2:一個Python庫,用于提取文檔信息和內(nèi)容乍构,逐頁拆分文檔甜无,合并文檔,裁剪頁面并添加水印哥遮。PyPDF2支持未加密和加密的文檔岂丘。

  • PDFMiner:完全用Python編寫,適用于Python 2.4眠饮。對于Python 3奥帘,請使用克隆的包PDFMiner.six。這兩個軟件包都允許您解析君仆,分析和轉(zhuǎn)換PDF文檔翩概。這包括對PDF 1.7以及CJK語言(中文,日文和韓文)的支持返咱,以及各種字體類型(Type1,TrueType牍鞠,Type3和CID)咖摹。

  • pdflib for Python:Poppler庫的擴展,為它提供了Python綁定难述。它使您可以解析萤晴,分析和轉(zhuǎn)換PDF文檔吐句。不要將其與具有相同名稱的商業(yè)吊墜相混淆。

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

  • PDFTables:一項商業(yè)服務,提供從PDF文檔附帶的表格中提取的內(nèi)容殖演。提供一個API氧秘,以便PDFTables可以用作SAAS。

  • PyX -Python圖形包:PyX是用于創(chuàng)建PostScript趴久,PDF和SVG文件的Python包丸相。它結(jié)合了PostScript繪圖模型的抽象和TeX / LaTeX接口。這些基元可以構(gòu)建復雜的任務彼棍,例如以可發(fā)布的質(zhì)量創(chuàng)建2D和3D繪圖灭忠。

  • ReportLab:一個雄心勃勃的,具有行業(yè)實力的圖書館座硕,主要致力于精確創(chuàng)建PDF文檔弛作。免費提供開放源代碼版本和名為ReportLab PLUS的商業(yè)增強版本。

  • PyMuPDF(又稱“ fitz”):MuPDF的Python綁定坎吻,這是一種輕量級的PDF和XPS查看器缆蝉。該庫可以訪問PDF,XPS瘦真,OpenXPS刊头,epub,漫畫和小說書格式的文件诸尽,并且以其最佳性能和高渲染質(zhì)量而聞名原杂。

  • pdfrw:一個基于Python的純PDF解析器,用于讀寫PDF您机。它忠實地再現(xiàn)矢量格式而無需光柵化穿肄。與ReportLab結(jié)合使用時,它有助于在使用ReportLab創(chuàng)建的新PDF中重用現(xiàn)有PDF的一部分际看。

圖書館 用于
PyPDF2
PyMuPDF
pdflib
PDF表格
PDFMiner.six
PDF查詢
pdfrw 讀咸产,寫/創(chuàng)作
PyFPDF 寫/創(chuàng)作

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

使用PyPDF2提取文本

$ pip3 install PyPDF2

清單1首先導入了PdfFileReader該類。接下來社牲,使用該類打開文檔粪薛,并使用getDocumentInfo()方法提取文檔信息,使用提取頁數(shù)getDocumentInfo()以及第一頁的內(nèi)容搏恤。

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

清單1:提取文檔信息和內(nèi)容痛阻。

#!/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所示菌瘪,提取的文本是連續(xù)打印的。沒有段落或句子分隔阱当。如PyPDF2文檔中所述俏扩,所有文本數(shù)據(jù)都按照在頁面內(nèi)容流中提供的順序返回,并且依靠它可能會導致一些意外弊添。這主要取決于PDF文檔的內(nèi)部結(jié)構(gòu)录淡,以及PDF編寫器過程如何生成PDF指令流。

使用PyMuPDF提取文本

可從PyPi網(wǎng)站上獲取PyMuPDF油坝,并在終端中使用以下命令安裝軟件包:

$ pip3 install PyMuPDF

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

清單2:使用PyMuPDF從PDF文檔中提取內(nèi)容。

#!/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的優(yōu)點是可以保持原始文檔結(jié)構(gòu)完整-帶有換行符的整個段落都保留在PDF文檔中(參見圖2)瞬女。

使用PyMuPDF從PDF提取圖像

PyMuPDF使用該方法簡化了從PDF文檔提取圖像的過程getPageImageList()窍帝。清單3基于PyMuPDF Wiki頁面上的示例,并逐頁地將PDF中的所有圖像提取并保存為PNG文件诽偷。如果圖像具有CMYK色彩空間坤学,則將首先將其轉(zhuǎn)換為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秒的時間內(nèi)提取了117張圖像深浮,這真是了不起。單個圖像以PNG格式存儲眠冈。為了保持原始圖像的格式和大小略号,而不是轉(zhuǎn)換為PNG,請查看PyMuPDF Wiki中腳本的擴展版本洋闽。

圖3:提取的圖像

使用PyPDF2將PDF拆分為頁面

對于此示例玄柠,首先需要同時導入PdfFileReader和和PdfFileWriter類。然后诫舅,我們打開PDF文件羽利,創(chuàng)建一個閱讀器對象,并使用閱讀器對象的getNumPages方法遍歷所有頁面刊懈。

for循環(huán)內(nèi)部这弧,我們創(chuàng)建的新實例PdfFileWriter,該實例尚不包含任何頁面虚汛。然后匾浪,使用pdfWriter.addPage()方法將當前頁面添加到我們的writer對象。此方法接受一個頁面對象卷哩,我們使用該PdfFileReader.getPage()方法獲取該對象蛋辈。

下一步是創(chuàng)建一個唯一的文件名,我們使用原始文件名加上單詞“ 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()方法,將檢測到搜索字符串的所有出現(xiàn)情況谷丸。如果匹配則在上面印有相應的信息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”一詞的搜索結(jié)果刨疼。

結(jié)論

此處顯示的處理PDF方法非常強大泉唁。使用相對較少的代碼行數(shù),很容易獲得結(jié)果揩慕。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末亭畜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子迎卤,更是在濱河造成了極大的恐慌拴鸵,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異劲藐,居然都是意外死亡八堡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門聘芜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來兄渺,“玉大人,你說我怎么就攤上這事汰现」业” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵瞎饲,是天一觀的道長口叙。 經(jīng)常有香客問我,道長嗅战,這世上最難降的妖魔是什么妄田? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮仗哨,結(jié)果婚禮上形庭,老公的妹妹穿的比我還像新娘。我一直安慰自己厌漂,他們只是感情好萨醒,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著苇倡,像睡著了一般富纸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上旨椒,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天晓褪,我揣著相機與錄音,去河邊找鬼综慎。 笑死涣仿,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的示惊。 我是一名探鬼主播好港,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼米罚!你這毒婦竟也來了钧汹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤录择,失蹤者是張志新(化名)和其女友劉穎拔莱,沒想到半個月后碗降,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡塘秦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年讼渊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗤形。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡精偿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出赋兵,到底是詐尸還是另有隱情,我是刑警寧澤搔预,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布霹期,位于F島的核電站,受9級特大地震影響拯田,放射性物質(zhì)發(fā)生泄漏历造。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一船庇、第九天 我趴在偏房一處隱蔽的房頂上張望吭产。 院中可真熱鬧,春花似錦鸭轮、人聲如沸臣淤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽邑蒋。三九已至,卻和暖如春按厘,著一層夾襖步出監(jiān)牢的瞬間医吊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工逮京, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留卿堂,地道東北人。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓懒棉,卻偏偏與公主長得像草描,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子漓藕,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容