大家好,歡迎來到 的編程教室 !
最近有同學提問說,能不能講一講識別發(fā)票圖片并整理數(shù)據(jù)到Excel里的方法。今天我們就針對這樣的實際需求,分享一個基于 PDF 的 辦公自動化的解決案例。
先來看看需求。
需求描述
在某個文件夾下有多個 PDF 類型發(fā)票
每一張發(fā)票 PDF 是純圖片類型,里面的文字信息無法手動復制(事實上大多數(shù)發(fā)票可以復制部分文字表格文字識別系統(tǒng),但我們?nèi)砸詧D片形式來講解),大致如下圖所示:
需要滿足的需求是:獲取 總金額、納稅人識別號、開票人表格文字識別系統(tǒng),即如下三個方框位置:
最后結(jié)合批量操作,在獲取上述信息后將其存儲入 Excel 中!
思路與代碼實現(xiàn)
需求本質(zhì)是一個圖片識別問題,因為 PDF 里的內(nèi)容是圖片類型,無法按常規(guī)方法直接把文本提取出來。解決思路是利用光學字符識別(OCR)將圖片中的文字識別出。但同時也需要注意,PDF 畢竟不是圖片,為了完成 OCR,除了OCR自身之外還要下載 和 用來完成類型轉(zhuǎn)換。以 系統(tǒng)為例,需要在電腦上安裝以下三個軟件:
32 位 32 位-OCR 32 位
三個軟件的下載安裝沒有特殊的地方( 配置稍復雜但網(wǎng)絡有上諸多教程,這里不再贅述),讀者可自行搜索下載及配置。
下面講解代碼。首先導入需要的模塊:
from?wand.image?import?Image
from?PIL?import?Image?as?PI
import?pyocr
import?pyocr.builders
import?io
import?re
import?os
import?shutil
具體的模塊用途可以參考下面具體代碼。其中 wand 和 pyocr 由于是非標準庫需要自行額外安裝。打開命令行輸入:
pip?install?wand
pip?install?pyocr
本需求還涉及對接 Excel,可考慮利用 庫的 用以創(chuàng)建新的 Excel 文件:
from?openpyxl?import?Workbook
需求中的 發(fā)票.pdf 放在桌面上。可通過下面基于 os 模塊的代碼獲取桌面路徑:
#?獲取桌面路徑包裝成一個函數(shù)
def?GetDesktopPath():
????return?os.path.join(os.path.expanduser("~"),?'Desktop')
path?=?GetDesktopPath()?+?r'\發(fā)票.pdf'
獲取配置好的 便于后面調(diào)用:
tool?=?pyocr.get_available_tools()[0]
通過 wand 模塊將 PDF 文件轉(zhuǎn)化為分辨率為 300 的 jpeg 圖片形式:
image_pdf?=?Image(filename=path,?resolution=300)
image_jpeg?=?image_pdf.convert('jpeg')
將圖片解析為二進制矩陣:
image_lst?=?[]
for?img?in?image_jpeg.sequence:
????img_page?=?Image(image=img)
????image_lst.append(img_page.make_blob('jpeg'))
用 io 模塊的 方法讀取二進制內(nèi)容為圖片形式:
new_img?=?PI.open(io.BytesIO(image_lst[0]))
new_img.show()
接下來分別截取需要提取部位字符串的圖片了,盡量讓圖片中只有需要識別的部分,獲取識別出來容易簡單處理獲得需要的內(nèi)容。
首先以總金額為例,截取圖片用 image.crop((left, top, right, )) 四個參數(shù)需要反復調(diào)試才能確定。經(jīng)確定四個參數(shù)分別是 1600 760 1830 900,嘗試截取和預覽圖片:
###?解析1Z開頭碼
left?=?350
top?=?600
right?=?1300
bottom?=?730
image_obj1?=?new_img.crop((left,?top,?right,?bottom))
image_obj1.show()
截取成功后可以交給 OCR 了,代碼為 tool.()
txt1=?tool.image_to_string(image_obj1)
print(txt1)
同樣,通過方位的調(diào)試就可以準確切割到需要的部分進行識別:
left?=?560
top?=?1260
right?=?900
bottom?=?1320
image_obj2?=?new_img.crop((left,?top,?right,?bottom))
#?image_obj2.show()
txt2?=?tool.image_to_string(image_obj2)
#?print(txt2)
最后是開票人的識別
left?=?1420
top?=?1420
right?=?1700
bottom?=?1500
image_obj3?=?new_img.crop((left,?top,?right,?bottom))
#?image_obj3.show()
txt3?=?tool.image_to_string(image_obj3)
#?print(txt3)
需要確認識別的內(nèi)容是否正確,如果識別正確率欠佳可以考慮通過圖片處理技術(shù)消除噪聲,也可以去官網(wǎng)下載更高精度的訓練包提高識別的正確性
至此,我們成功的識別了總金額、納稅人識別號、開票人三個消息,接下來就通過非常熟悉的 寫入Excel,并使用 os 模塊實現(xiàn)批量操作即可
workbook?=?Workbook()
sheet?=?workbook.active
header?=?['總金額',?'納稅人識別號',?'開票人']
sheet.append(header)
sheet.append([txt1,?txt2,?txt3])
workbook.save(GetDesktopPath()?+?r'\匯總.xlsx')
綜上,整個需求就成功實現(xiàn),從效果來看還是非常不錯的!完整源碼可由文中代碼組合而成(已全部分享在文中),感興趣的讀者可以自己嘗試!
最后想說的是,其實本文的案例可以衍生出很多實用的辦公自動化腳本,例如
大家有類似的需求也可以在文章下面留言,我們之后會優(yōu)先考慮相關(guān)的學習案例。
如果文章對你有幫助,歡迎轉(zhuǎn)發(fā)/點贊/收藏~