解放雙手!Python提取PDF指定內(nèi)容,并批量重命名文件!
大家好,本文將分享一個常見辦公場景下的Python自動化案例,主要將涉及以下兩個內(nèi)容。
Python提取圖片型PDF內(nèi)容 Python批量重命名文件
一、需求描述
有一個文件夾 貨物清單 中含有多張貨物清單的影印版 PDF,分別命名為 文件 (1).pdf 文件 (2).pdf ... 文件 (20).pdf,如下所示:
PDF 是純圖片類型,里面的文字信息無法手動復(fù)制,同時本例中所有的圖片都向左旋轉(zhuǎn) 90 度,大致如下圖所示(馬賽克部分為無關(guān)內(nèi)容):
我們需要做的是 「 獲取圖中紅框部分 TRACKING# 以及 REF2 冒號后的字符串,用 & 連接后重命名這個 PDF 文件 」 !
也就是需要根據(jù)每個PDF內(nèi)容來批量重命名一大堆文件,最終效果如下
二、邏輯梳理與基礎(chǔ)配置
本需求是一個批處理問題,即需要對諸多文件執(zhí)行類型的操作,基本思路是先完成對一份文件的處理,然后借助 glob 模塊獲取指定路徑所有符合要求的文件路徑,執(zhí)行批處理框架,固后面的操作先針對 文件 (1).pdf
需求中最大的難題在于,PDF 是圖片類型,無法按常規(guī)方法提取文件。解決思路是利用光學(xué)字符識別(OCR)將圖片中的文字識別出,然后進(jìn)行后續(xù)操作,這里就涉及到一些先后順序:
將圖片向右旋轉(zhuǎn)回正位 截取需要識別的部分圖片 將截取的圖片交給 OCR 獲取字符串
為了完成 OCR,需要在電腦上安裝三個軟件:
Ghostscript32 位ImageMagick32 位tesseract-OCR32 位
三個軟件的下載安裝沒有特殊的地方(tesseract 配置稍復(fù)雜但網(wǎng)絡(luò)有上諸多教程,這里不再贅述),讀者可自行搜索下載及配置
三、代碼實現(xiàn)
首先導(dǎo)入需要的模塊:
from wand.image import Image
from PIL import Image as PI
import pyocr
import pyocr.builders
import io
import glob
import re
import os
import shutil
具體的模塊用途可以參考下面具體代碼。其中 wand 和 pyocr 由于是非標(biāo)準(zhǔn)庫需要自行額外安裝。打開命令行輸入:
pip install wand
pip install pyocr
作為測試以及方便后面的實際運(yùn)行,需求中的 貨物清單 這一文件夾可以放在桌面上。為了獲取其中的內(nèi)容首先我們要明確桌面的路徑。每個人每臺電腦的桌面路徑都不相同,如果直接復(fù)制當(dāng)前電腦桌面的路徑,更換電腦或者其他用戶調(diào)試就需要額外修改。可通過下面基于 os 模塊的代碼獲取桌面路徑:
# 獲取桌面路徑包裝成一個函數(shù)
def GetDesktopPath():
return os.path.join(os.path.expanduser("~"), 'Desktop')
path = GetDesktopPath() + r'\貨物清單' # 獲取 貨物清單 文件夾路徑
獲取配置好的 tesseract 便于后面調(diào)用:
tool = pyocr.get_available_tools()[0]
以 文件 (1).pdf 為例,通過 wand 模塊將 PDF 文件轉(zhuǎn)化為分辨率為 300 的 jpeg 圖片形式:
image_pdf = Image(filename=path + r'\文件 (1).pdf', resolution=300)
image_jpeg = image_pdf.convert('jpeg')
將圖片解析為二進(jìn)制矩陣:
image_lst = []
for img in image_jpeg.sequence:
img_page = Image(image=img)
image_lst.append(img_page.make_blob('jpeg'))
用 io 模塊的 BytesIO 方法讀取二進(jìn)制內(nèi)容為圖片形式:
new_img = PI.open(io.BytesIO(image_lst[0]))
由于圖片現(xiàn)在處于左旋 90 度的水平位,將其轉(zhuǎn)為正位可以用 rotate() 方法,注意該方法是逆時針旋轉(zhuǎn),因此回正位需要逆時針旋轉(zhuǎn) 270 度。完善上面的代碼,并為 new_img.show() 預(yù)覽圖片:
new_img = PI.open(io.BytesIO(image_lst[0])).rotate(270)
new_img.show()

彈出圖片并恢復(fù)到了正位,接下來分別截取需要提取部位字符串的圖片了,盡量讓圖片中只有需要識別的部分,獲取識別出來容易簡單處理獲得需要的內(nèi)容
截取圖片用 image.crop((left, top, right, bottom)) 四個參數(shù)需要反復(fù)調(diào)試才能確定。首先提取 TRACKING# 部位需要的內(nèi)容,經(jīng)確定四個參數(shù)分別是 350 600 1350 730,嘗試截取和預(yù)覽圖片:
### 解析1Z開頭碼
left = 350
top = 600
right = 1300
bottom = 730
image_obj1 = new_img.crop((left, top, right, bottom))
image_obj1.show()

截取成功后可以交給 OCR 了,代碼為 tool.image_to_string()
txt1= tool.image_to_string(image_obj1)
print(txt1)

通過正則提取紅框內(nèi)需要的內(nèi)容:
req = 'TRACKING #: (.*)'
txt1_real = ''.join(re.findall(req, txt1)[0].split())
print(txt1_real)

用同樣的辦法也可以提取另一個紅框的文字:
### 解析C開頭碼
left = 205
top = 1170
right = 2450
bottom = 1200
image_obj2 = new_img.crop((left, top, right, bottom))
txt2 = tool.image_to_string(image_obj2)
req = 'C.\d+\d'
txt2_real = re.findall(req, txt2)[0]
最后將兩個字符串和 & 拼接為長字符串,然后通過 os.rename() 完成重命名文件的目的:
file_name = txt1_real + '&' + txt2_real
os.rename(path + r'\文件 (1).pdf', path + r'\{}.pdf'.format(file_name))
至此我們就完成了需求的一大步,接下來只需要借助 glob 模塊遍歷目標(biāo)文件夾,對獲取的每一個文件執(zhí)行上面的操作即可,這樣就將全部需求完成,所有的PDF均按照指定字段進(jìn)行重命名
本文的分享就到這里,上面的 Python辦公自動化 案例可以擴(kuò)展到很多使用場景(核心為提取PDF指定內(nèi)容+批量重命名),大家可以自己找一些文件測試學(xué)習(xí),如果對你有所幫助可以給本文來一波三連
-end-
