用python處理excel數據「python提取數據指定列」

本文分享一個基於 PDF 的 Python 辦公自動化的案例解決,也是某位財務小姐姐提出的真實需求,先來看看需求。

需求描述

在某個文件夾下有多個 PDF 類型發票

解放雙手|Python 批量自動提取、整理 PDF 發票

每一張發票 PDF 是純圖片類型,裡面的文字信息無法手動複製(事實上大多數發票可以複製部分文字,但我們扔以圖片形式來講解),大致如下圖所示:

解放雙手|Python 批量自動提取、整理 PDF 發票

需要滿足的需求是:獲取 總金額、納稅人識別號、開票人,即如下三個方框位置:

解放雙手|Python 批量自動提取、整理 PDF 發票

最後結合批量操作,在獲取上述信息後將其存儲入 Excel 中!

解放雙手|Python 批量自動提取、整理 PDF 發票

思路與代碼實現

需求本質是一個圖片識別問題,因為 PDF 里的內容是圖片類型,無法按常規方法直接把文本抽提出來。解決思路是利用光學字元識別(OCR)將圖片中的文字識別出。但同時也需要注意,PDF 畢竟不是圖片,為了完成 OCR,除了OCR自身之外還要下載 Ghostscript 和 ImageMagick 用來完成類型轉換。已 Windows 系統為例,需要在電腦上安裝以下三個軟體:

  1. Ghostscript 32 位
  2. ImageMagick 32 位
  3. tesseract-OCR 32 位

三個軟體的下載安裝沒有特殊的地方(tesseract 配置稍複雜但網路有上諸多教程,這裡不再贅述),讀者可自行搜索下載及配置,下面講解代碼。首先導入需要的模塊:

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,可考慮利用 openpyxl 庫的 Workbook 用以創建新的 Excel 文件:

from openpyxl import Workbook

需求中的 發票.pdf 放在桌面上。可通過下面基於 os 模塊的代碼獲取桌面路徑:

# 獲取桌面路徑包裝成一個函數
def GetDesktopPath():
    return os.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 = []
for img in image_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 = 350
top = 600
right = 1300
bottom = 730
image_obj1 = new_img.crop((left, top, right, bottom))
image_obj1.show()
解放雙手|Python 批量自動提取、整理 PDF 發票

截取成功後可以交給 OCR 了,代碼為 tool.image_to_string()

txt1= tool.image_to_string(image_obj1)
print(txt1)
解放雙手|Python 批量自動提取、整理 PDF 發票

同樣,通過方位的調試就可以準確切割到需要的部分進行識別:

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)

最後是開票人的識別

解放雙手|Python 批量自動提取、整理 PDF 發票

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)

解放雙手|Python 批量自動提取、整理 PDF 發票

需要確認識別的內容是否正確,如果識別正確率欠佳可以考慮通過圖片處理技術消除雜訊,也可以去官網下載更高精度的訓練包提高識別的正確性

至此,我們成功的識別了總金額、納稅人識別號、開票人三個消息,接下來就通過非常熟悉的 openpyxl 寫入Excel,並使用 os 模塊實現批量操作即可

workbook = Workbook()
sheet = workbook.active
header = ['總金額', '納稅人識別號', '開票人']
sheet.append(header)
sheet.append([txt1, txt2, txt3])
workbook.save(GetDesktopPath() + r'匯總.xlsx')
解放雙手|Python 批量自動提取、整理 PDF 發票

綜上,整個需求就成功實現,從效果來看還是非常不錯的!完整源碼可由文中代碼組合而成(已全部分享在文中),感興趣的讀者可以自己嘗試!

最後想說的是,其實本文的案例可以衍生出很多實用的辦公自動化腳本,例如

  • 批量計算髮票金額並重命名文件夾
  • 根據發票類型批量分類
  • 根據發票批量製作報銷單
  • ··· ···

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/255719.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-15 12:30
下一篇 2024-12-15 12:30

相關推薦

發表回復

登錄後才能評論