python提取某一列數據 python 提取列



文章插圖
python提取某一列數據 python 提取列

文章插圖
本文分享一個基于 PDF 的 Python 辦公自動化的案例解決 , 也是某位財務小姐姐提出的真實需求 , 先來看看需求 。
需求描述
在某個文件夾下有多個 PDF 類型發票
每一張發票 PDF 是純圖片類型 , 里面的文字信息無法手動復制(事實上大多數發票可以復制部分文字 , 但我們扔以圖片形式來講解) , 大致如下圖所示:
需要滿足的需求是:獲取 總金額、納稅人識別號、開票人 , 即如下三個方框位置:
最后結合批量操作 , 在獲取上述信息后將其存儲入 Excel 中!
思路與代碼實現
需求本質是一個圖片識別問題 , 因為 PDF 里的內容是圖片類型 , 無法按常規方法直接把文本抽提出來 。解決思路是利用光學字符識別(OCR)將圖片中的文字識別出 。但同時也需要注意 , PDF 畢竟不是圖片 , 為了完成 OCR , 除了OCR自身之外還要下載 Ghostscript 和 ImageMagick 用來完成類型轉換 。已 Windows 系統為例 , 需要在電腦上安裝以下三個軟件:
Ghostscript 32 位ImageMagick 32 位tesseract-OCR 32 位
三個軟件的下載安裝沒有特殊的地方(tesseract 配置稍復雜但網絡有上諸多教程 , 這里不再贅述) , 讀者可自行搜索下載及配置 , 下面講解代碼 。首先導入需要的模塊:
fromwand.imageimportImagefromPILimportImageasPIimportpyocrimportpyocr.buildersimportioimportreimportosimportshutil具體的模塊用途可以參考下面具體代碼 。其中 wand 和 pyocr 由于是非標準庫需要自行額外安裝 。打開命令行輸入:
pipinstallwandpipinstallpyocr本需求還涉及對接 Excel , 可考慮利用 openpyxl 庫的 Workbook 用以創建新的 Excel 文件:
fromopenpyxlimportWorkbook【python提取某一列數據 python 提取列】需求中的 發票.pdf 放在桌面上 。可通過下面基于 os 模塊的代碼獲取桌面路徑:
#獲取桌面路徑包裝成一個函數defGetDesktopPath():returnos.path.join(os.path.expanduser("~"),'Desktop')path=GetDesktopPath()+r'發票.pdf'獲取配置好的 tesseract 便于后面調用:
tool=pyocr.get_available_tools()[0]通過 wand 模塊將 PDF 文件轉化為分辨率為 300 的 jpeg 圖片形式:
image_pdf=Image(filename=path,resolution=300)image_jpeg=image_pdf.convert('jpeg')將圖片解析為二進制矩陣:
image_lst=[]forimginimage_jpeg.sequence:img_page=Image(image=img)image_lst.append(img_page.make_blob('jpeg'))用 io 模塊的 BytesIO 方法讀取二進制內容為圖片形式:
new_img=PI.open(io.BytesIO(image_lst[0]))new_img.show()接下來分別截取需要提取部位字符串的圖片了 , 盡量讓圖片中只有需要識別的部分 , 獲取識別出來容易簡單處理獲得需要的內容 。
首先以總金額為例 , 截取圖片用 image.crop((left, top, right, bottom)) 四個參數需要反復調試才能確定 。經確定四個參數分別是 1600 760 1830 900 , 嘗試截取和預覽圖片:
###解析1Z開頭碼left=350top=600right=1300bottom=730image_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)
同樣 , 通過方位的調試就可以準確切割到需要的部分進行識別:
left=560top=1260right=900bottom=1320image_obj2=new_img.crop((left,top,right,bottom))#image_obj2.show()txt2=tool.image_to_string(image_obj2)#print(txt2)最后是開票人的識別
left = 1420top = 1420right = 1700bottom = 1500image_obj3 = new_img.crop((left, top, right, bottom))# image_obj3.show()txt3 = tool.image_to_string(image_obj3)# print(txt3)
需要確認識別的內容是否正確 , 如果識別正確率欠佳可以考慮通過圖片處理技術消除噪聲 , 也可以去官網下載更高精度的訓練包提高識別的正確性
至此 , 我們成功的識別了總金額、納稅人識別號、開票人三個消息 , 接下來就通過非常熟悉的 openpyxl 寫入Excel , 并使用 os 模塊實現批量操作即可
workbook=Workbook()sheet=workbook.activeheader=['總金額','納稅人識別號','開票人']sheet.append(header)sheet.append([txt1,txt2,txt3])workbook.save(GetDesktopPath()+r'匯總.xlsx')
綜上 , 整個需求就成功實現 , 從效果來看還是非常不錯的!完整源碼可由文中代碼組合而成(已全部分享在文中) , 感興趣的讀者可以自己嘗試!
最后想說的是 , 其實本文的案例可以衍生出很多實用的辦公自動化腳本 , 例如
批量計算發票金額并重命名文件夾根據發票類型批量分類根據發票批量制作報銷單··· ···