上乾貨!教你用Python GUI框架生成圖片提取器!WORD、PDF都能用上它

前言:

大家好,今天教大家做一個綜合性較強的Python實戰練習:

用Python提取PDF與Word中的圖片

要想實現我們今天的主題,首先不得不涉及到Python中一個非常常見的框架內容GUI,以前我們在文章中也有講過一些涉及 python GUI 框架的開發案例;其次是利用Python進行excel/word/pdf 等文件的讀寫,這一內容在以前的文章中也有講解。那麼今天我們需要做的,便是將這兩個內容靈活的結合起來,做出分析,並結合GUI框架

PysimpleGUI

,做一個

多檔案圖片提取軟體。

如圖所示:

本文主要將分為以下部分講解:

PDF、Word 檔案圖片提取

構造圖片提取器GUI框架

整合程式碼並打包

主要涉及的Python模組有:

PIL

PySimpleGUI

re

win32

os

zipfile

fitz

模組安裝

首先使用pip安裝相關依賴模組

pip install pillow   #這是對模組PTL的安裝

pip install pypiwin32    #這是對win32的安裝pip install os

pip install zipfile

pip install PyMuPDF  #這是引用fitz對PDF操作的包

pip install PySimpleGui

一、提取各檔案內嵌圖片

讀取Excel有兩種方法。一種是將字尾名改成

。zip

格式進行提取,一種是透過

Pillow

模組對Excel進行圖片複製與儲存。Word提取圖片方法和透過

。zip

提取方法類似,PDF提取圖片方法要用到專門的模組。

這篇文章裡只對PDF和Word的提取方法展開講解

,Excel 的讀取方法類似,可參見程式碼。

1。1 提取Word圖片

我們先看程式碼

path = values[“lujing”]

count = 1for file in os。listdir(path):

new_file = file。replace(“。docx”,“。zip”)

os。rename(os。path。join(path,file),os。path。join(path,new_file))

count+=1

number = 0

craterDir = values[“lujing”] + ‘/’  # 存放zip檔案的資料夾路徑

saveDir = values[“lujing”] + ‘/’ # 存放圖片的路徑

list_dir = os。listdir(craterDir) # 獲取所有的zip檔名

for i in range(len(list_dir)):        if ‘zip’ not in list_dir[i]:

list_dir[i] = ‘’

while ‘’ in list_dir:

list_dir。remove(‘’)

for zip_name in list_dir:                    # 預設模式r,讀

azip = zipfile。ZipFile(craterDir + zip_name)                    # 返回所有資料夾和檔案

namelist = (azip。namelist())                    for idx in range(0,len(namelist)):                        if namelist[idx][:11] == ‘word/media/’:#圖片是在這個路徑下

img_name = saveDir + str(number)+‘。jpg’

f = azip。open(namelist[idx])

img = Image。open(f)

img = img。convert(“RGB”)

img。save(img_name,“JPEG”)

number += 1

azip。close()  #關閉檔案,必須有,釋放記憶體

這裡的程式碼和透過

。zip

方式提取Excel圖片的程式碼思路是一樣的。

path = values[“lujing”]

這裡是讀取GUI中鍵為

“lujing”

的值,也即檔案儲存位置,用於os模組讀取與操作。

new_file = file。replace(“。docx”,“。zip”)

是替換字尾名,如果是Excel的話,就把

。docx

改成

。xlsx

xls

craterDir = values[“lujing”] + ‘/’

這是存放zip檔案的資料夾路徑,注意這裡讀取到的鍵為“lujing”的值後要在後面新增

/

saveDir = values[“lujing”] + ‘/’

這是存放圖片的路徑,同理,和上面一樣加個

/

號。

最後說一下與Excel提取相比,

最大的不同是下面的程式碼

if namelist[idx][:11] == ‘word/media/’:

中括號裡面的值不一樣。很好理解,我們可以列印

namelist[idx]

,可以發現在索引0到10是

‘word/media/’

所在位置。而在Excel中是前9位。

1。2 提取PDF圖片

先來看看相關程式碼:

def pdf2pic(path, pic_path):

doc = fitz。open(path)

nums = doc。_getXrefLength()

imgcount = 0

for i in range(1, nums):

text = doc。_getXrefString(i)        if (‘Width 2550’ in text) and (‘Height 3300’ in text) or (‘thumbnail’ in text):            continue

checkXO = r“/Type(?= */XObject)”

checkIM = r“/Subtype(?= */Image)”

isXObject = re。search(checkXO, text)

isImage = re。search(checkIM, text)            if not isXObject or not isImage:                continue

imgcount += 1

pix = fitz。Pixmap(doc, i)

img_name = “img{}。png”。format(imgcount)                if pix。n < 5:                    try:

pix。writePNG(os。path。join(pic_path, img_name))

pix = None

except:

pix0 = fitz。Pixmap(fitz。csRGB, pix)

pix0。writePNG(os。path。join(pic_path, img_name))

pix0 = Noneif __name__ == ‘__main__’:

path = values[“lujing”]+ ‘/’ + values[“wenjian”]

pic_path = values[“lujing”]

pdf2pic(path, pic_path)

先說一下這段程式碼的思路吧,

由於PDF不能像Excel和Word一樣改字尾名進行提取

,故這裡運用python的一個模組

PyMuPDF

,過程如下

讀取PDF並遍歷每一頁

篩選無用的元素並用正則表示式獲取圖片

生成並儲存圖片

fitz。open(path)

是開啟PDF資料夾,這裡的path是需要在GUI介面中獲取使用者的檔案存放路徑與檔名的。

for i in range(1, nums):

text = doc。_getXrefString(i)

這是我們的第一步讀取並遍歷,將讀取到的字串內容放入到text中

if (‘Width 2550’ in text) and (‘Height 3300’ in text) or (‘thumbnail’ in text): continue

由於PDF每一頁的背景就是一張圖片,故我們可以透過寬高來尋找這些背景圖片並用continue把他們剔除。

checkXO = r“/Type(?= */XObject)”checkIM = r“/Subtype(?= */Image)”isXObject = re。search(checkXO, text)

isImage = re。search(checkIM, text)if not isXObject or not isImage:    continue

我們透過實驗發現圖片所對應的字串在

checkxo

checkIM

這兩個中。故用

正則表示式

在text中進行索引提取,用到了

re

模組的search函式。如果不是這兩個字串就用continue剔除。

pix = fitz。Pixmap(doc, i)

img_name = “img{}。png”。format(imgcount)if pix。n < 5: try:

pix。writePNG(os。path。join(pic_path, img_name))

pix = None

except:

pix0 = fitz。Pixmap(fitz。csRGB, pix)

pix0。writePNG(os。path。join(pic_path, img_name))

pix0 = None

這是最後一步生成與儲存圖片

pix = fitz。Pixmap(doc, i)

是生成影象語句,doc代表PDF檔案,i代表遍歷每個圖片物件的索引值。

img_name = “img{}。png”。format(imgcount)

是設定影象名語句,用提取到的圖片的序列號作為命名格式。

而後if巢狀try那幾行程式碼是儲存影象語句。如果pix。n<5,可以直接存為PNG,否者將進行RGB變換在儲存。

最後,傳遞引數,呼叫函式。

完成了圖片的提取,接下來就是 GUI 的構建了。

二、GUI框架的構建

先看完整程式碼:

import PySimpleGUI as sg

sg。ChangeLookAndFeel(‘GreenTan’)   #更換主題menu_def = [[‘&使用說明’, [‘&注意’]]]

layout = [

[sg。Menu(menu_def, tearoff=True)],

[sg。Frame(layout=[

[sg。Radio(‘Excel1’, “RADIO1”,size=(10,1),key=“Excel1”),  sg。Radio(‘Word’, “RADIO1”,default=True,key=“Word”)],

[sg。Radio(‘Excel2’, “RADIO1”, enable_events=True, size=(10,1),key=“Excel2”), sg。Radio(‘PDF’, “RADIO1”,key=“PDF”)]], title=‘選項’,title_color=‘red’, relief=sg。RELIEF_SUNKEN, tooltip=‘Use these to set flags’)],

[sg。Text(‘檔案位置’, size=(8, 1), auto_size_text=False, justification=‘right’),

sg。InputText(enable_events=True,key=“lujing”), sg。FolderBrowse()],

[sg。Text(‘檔名字’, size=(8, 1), justification=‘right’),

sg。InputText(enable_events=True,key=“wenjian”)],

[sg。Submit(tooltip=‘檔案’), sg。Cancel()]]

window = sg。Window(‘圖片提取器’, layout, default_element_size=(40, 1), grab_anywhere=False)while True:

event, values = window。read()    if event == “Submit”:        if values[“Excel2”] == True:   ‘’‘

事件繫結

’‘’

sg。Popup(“提取成功”)        if values[“Excel1”] == True:   ‘’‘

事件繫結

’‘’

sg。Popup(“提取成功”)        if values[“Word”] == True:   ‘’‘

事件繫結

’‘’

sg。Popup(“提取成功”)

if values[“PDF”] == True:   ‘’‘

事件繫結

’‘’

sg。Popup(“提取成功”)    if event == “Cancel” or event == sg。WIN_CLOSED:        break

if event == “注意”:

sg。Popup(“作用講解:”,                 “Excel1 :解析選定位置中所有的Excel檔案,無需在檔名處填寫”,                 “Excel2 :解析選定位置中單個指定的Excel檔案,需在檔名處填寫”,                 “Word :  解析選定位置中單個指定的docx結尾的檔案,無需在檔名處填寫”,                 “PDF :   解析選定位置中單個指定的PDF檔案,需在檔名處填寫”)

window。close()

效果呈現:

程式碼解析:做

PySimpleGUI

還是原來那個步驟:

Import ☞ Create some widgets ☞ Create the window ☞ Create the event loop

當然,

做GUI之前就是先想清楚自己的圖形互動頁面長什麼樣,像我就是現在紙上畫一個大概,這樣更有益於製作頁面

第一步

:引用模組

第二步:新增元素

(小部件)到容器(layout)中,這裡先介紹一下用到的部件:

Menu

:顧名思義,這是選單欄,每個GUI都必帶一個選單欄來提示使用者該如何做,我們這裡用了

menu_def

這個佈局來完成選單的設定。

Frame

:這個跟layout佈局完全相同,工作方式也一樣,他們都是容器元素。可以看到“選項”那裡是一個凹槽的正方形,裡面裝有四個選項,作用就是這個。注意,

&

這個符號的作用是建立相同型別的選單,這裡只有注意事項這一個選單,故可以不用管,讀者如果想新增同樣的選單的話必須新增一個

&

tearoff=True

這個引數是選單欄中每個子選項上面加虛線。

Radio

:單選按鈕。我們只可以在同樣的id上選擇一個選項。id就是指程式碼中的“ra-dio1”。其中每個radio函式的第一個引數是文字內容,這裡就是我們要進行提取的4個檔案格式。而“size”就是位置,每行的第一個設同樣的引數(10,1)。最後就是我們進行事件繫結的鍵,其中“enable_events”可以不寫因為我們只是呼叫它而不用去對它產生事件。

Text

:之前有講是不能改的正文內容。同樣這裡設定的位置引數(8,1),

justification=‘right’

有點類似我們平常用word那個向右對齊。

InputText

:需要使用者輸入的正文內容。這裡有兩個需要我們填寫的地方:檔案位置和檔名。這裡需要設定鍵,因為在後面事件繫結中我們需要呼叫檔案儲存路徑和檔名,在文中上半部分有提到過。

FolderBrowse

:簡易的開啟檔案路徑操作,不用你去複製路徑。

Submit

:確定按鈕,這裡繫結為執行提取文件圖片事件

Cancel

:退出主程式按鈕。

第三步:建立視窗

來容納這些元素佈置。

第四步:建立事件迴圈

,可以看到程式碼,都是一樣的套路:當用戶按下submit按鈕時系統將進行判斷你按的是哪個單選按鈕,進而進行相對應的事件執行。當你按下cancel或者

×

時,就是退出主程式。當你按選單中的注意時,就會彈出一個對話方塊告訴你這個系統怎麼用。

在事件迴圈中,我們用

values[]

的布林值來判斷我們選的是哪個單選按鈕,有讀者疑問為什麼不用

event=

,因為我們在第一個if當中用了event所以第二個if當中需要換一個判斷方法。

至此,GUI部分就搞定了!感興趣的讀者可以繼續在上面新增功能。

三、整合程式碼並打包

我們將完整程式碼整合在一起,後安裝

pyinstaller

模組

pip install pyinstaller

如果你的上述專案程式碼檔案命名為:

photo。py

。那麼你要用下面命令進行打包

pyinstaller photo。py

最後打包成功之後,你會在py檔案所在資料夾看到一個

dist

的子資料夾。進去之後,找到

pachong。exe

檔案並執行它即可。

注意,資料夾裡附帶了很多檔案,你可以刪除它。當然,如果嫌麻煩就直接從

photo。py

檔案用Python執行。

寫在最後

今天的內容就到這裡啦,希望可以對你有所幫助。如果有需要本文原始碼的同學可以私信我關鍵字:

PY GUI

,我會將原始碼分享給有需要的人。

也歡迎各路大神在評論區提出問題與建議,希望能與大家共同進步。

相關文章