Python으로 카드내역 작성 자동화하기
현재 회사에서는 법인카드를 일정 금액 내에서 사용할 수 있는데, 달마다 사용내역을 제출해야 합니다.
물론 회사에 따라 카드사에서 직접 엑셀을 제공해 주기도 하지만, 지금은 그렇지 않아 수기로 작성해야 하는데 내역을 핸드폰으로 확인해 일일이 엑셀에 옮겨 적는 게 너무 귀찮았습니다.
그래서 어떻게든 엑셀을 쓰지 말자라는 생각으로 삽질자동화를 열심히 진행했던 내용을 적어 보려고 합니다.
핵심 아이디어: OCR
앱에서 카드 사용내역 정보를 얻는 방법은 크게 2가지 정도가 생각이 났습니다.
첫 번째는 카드승인 시 오는 알림 등에서 패킷을 긁어 정보를 빼내는 건데... 그다지 자신이 없고 설사 가능하더라도 보안을 뚫는 느낌이라 바람직한 방법은 아니라고 생각했습니다. 그래서 다른 방법을 생각했고 그 방법은 바로 스크린샷을 찍어 OCR 인식으로 내역을 추출하는 것이었습니다.
문제는 오픈소스(무료) OCR 도구의 한글 인식률이 영 좋지 않다는 점이었습니다. 여러 시행착오를 거쳐 보았지만 번거롭기만 하고 결과도 그리 만족스럽지 않았습니다. 결국 생각나는 것은 네이버◦카카오 등 국내에서 제공하는 OCR인데, 유료라는 점이 역시 걸렸습니다.
그러던 중 CLOVA OCR 체험 페이지를 찾게 되었는데, 체험 명목으로 적은 양이지만 무료로 사진 몇 개를 업로드해 OCR 결과를 받을 수 있었습니다. 그래서 해당 페이지를 Selenium으로 조작해 OCR 인식 결과를 얻으면 되겠다는 생각을 했고, 실제로 만족스러운 결과를 얻을 수 있었습니다.
이전 방식: FastAPI
OCR 문제는 해결되었고, 이제 스크린샷을 처리할 방법만 생각하면 되었습니다.
스크린샷은 모바일에서 찍을 텐데, 처리를 위해 컴퓨터에 옮기는 것도 하나의 일이라고 생각했습니다.
그래서 가장 먼저 생각난 것이 REST API였습니다.
바로 FastAPI로 파일을 받 아서, OCR로 처리하고 자동으로 엑셀까지 작성해 다운로드할 수 있도록 작업했습니다. 작업에 시간이 걸리기 때문에, 백그라운드 작업으로 처리하도록 하였습니다. 실사용까지 성공은 했는데, 몇 가지 문제가 있었습니다.
- 사용량이 적었습니다. 이를 위해 VM을 올리는 것은 다소 낭비였습니다.
- Selenium은 브라우저를 돌려야 하기 때문에 무료 VM으로는 메모리 압박이 심했습니다.
- VM에서 백그라운드로 돌리다 보니 에러 로깅이 쉽지 않았습니다. 파일로 로그를 빼는 등 방법이 없는 것은 아니었지만 배보다 배꼽이 더 크기도 하고...
그러다가 기존에 VM을 띄워 놓았던 Oracle Cloud 계정이 개인적인 문제로 터지면서(...) 이 방법은 폐기하게 되었습니다.
현재 방식: Google Drive API
곰곰이 생각해 보니, 엑셀 파일은 어차피 메일로 보내야 하고 이래저래 개인 컴퓨터에서 코드를 돌려도 상관없겠다 싶었습니다. 그리고 모바일로 파일을 올리고 처리할 수 있는 다른 방법으로 클라우드 스토리지가 머리를 스쳐갔습니다. 가장 친숙한 Google Drive로 실행에 옮겨 보기로 했습니다.
그래서 다음과 같은 식으로 코드를 작성했습니다.
import os
import shutil
import config
from func.gdrive import gdrive_down, gdrive_up_excel
from func.img_process import crop_and_save
from func.ocr import make_excel_ocr
IMG_FOLDER = "download"
# 폴더 세팅
if os.path.exists(IMG_FOLDER):
shutil.rmtree(IMG_FOLDER)
os.makedirs(IMG_FOLDER, exist_ok=True)
# 파일 다운로드
gdrive_down(folderName=config.GDRIVE_FOLDER_NAME)
# 파일 전처리
for file in os.listdir(IMG_FOLDER):
crop_and_save(fileName=file, folder=IMG_FOLDER)
# 파일 CLOVA로 OCR 처리해서 엑셀 작성
fileName = make_excel_ocr(
folderName=IMG_FOLDER,
cardName=config.CARD_NAME,
name=config.NAME,
year=config.YEAR,
month=config.MONTH
)
# 엑셀 파일 업로드
gdrive_up_excel(fileName=fileName)
파일 전처리는 간단히 Pillow
패키지를 사용해 이미지를 자르는 과정이고, OCR을 통한 처리는 기존대로 Selenium을 활용했습니다.
Google Drive API를 사용하기 위해서는 초기 설정이 필요한데, 이 부분은 공식 문서에 잘 설명되어 있습니다. 오히려 이후에 Python 패키지를 사용하는 과정이 번거로웠습니다. 구글에서 제공하는 예제가 2% 부족하고, 과거 API 버전 기준의 정보도 다수 혼재해 있었기 때문입니다. 그래도 간단한 다운로드◦업로드만 구현하면 되었기 때문에 몇 가지 참고 자료를 찾아가며 진행했습니다.
핵심 로직은 변경이 없었기 때문에 추가적인 공수가 많이 들어가지 않았고, 현재 문제없이 사용 중입니다.