
ํ์ฌ ํ์ฌ์์๋ ๋ฒ์ธ์นด๋๋ฅผ ์ผ์ ๊ธ์ก ๋ด์์ ์ฌ์ฉํ ์ ์๋๋ฐ, ๋ฌ๋ง๋ค ์ฌ์ฉ๋ด์ญ์ ์ ์ถํด์ผ ํฉ๋๋ค.
๋ฌผ๋ก ํ์ฌ์ ๋ฐ๋ผ ์นด๋์ฌ์์ ์ง์ ์์
์ ์ ๊ณตํด ์ฃผ๊ธฐ๋ ํ์ง๋ง, ์ง๊ธ์ ๊ทธ๋ ์ง ์์ ์๊ธฐ๋ก ์์ฑํด์ผ ํ๋๋ฐ ๋ด์ญ์ ํธ๋ํฐ์ผ๋ก ํ์ธํด ์ผ์ผ์ด ์์
์ ์ฎ๊ฒจ ์ ๋ ๊ฒ ๋๋ฌด ๊ท์ฐฎ์์ต๋๋ค.
๊ทธ๋์ ์ด๋ป๊ฒ๋ ์์
์ ์ฐ์ง ๋ง์๋ผ๋ ์๊ฐ์ผ๋ก ์ฝ์ง์๋ํ๋ฅผ ์ด์ฌํ ์งํํ๋ ๋ด์ฉ์ ์ ์ด ๋ณด๋ ค๊ณ ํฉ๋๋ค.
ํต์ฌ ์์ด๋์ด: 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 ๋ฒ์ ๊ธฐ์ค์ ์ ๋ณด๋ ๋ค์ ํผ์ฌํด ์์๊ธฐ ๋๋ฌธ์ ๋๋ค. ๊ทธ๋๋ ๊ฐ๋จํ ๋ค์ด๋ก๋โฆ์ ๋ก๋๋ง ๊ตฌํํ๋ฉด ๋์๊ธฐ ๋๋ฌธ์ ๋ช ๊ฐ์ง ์ฐธ๊ณ ์๋ฃ๋ฅผ ์ฐพ์๊ฐ๋ฉฐ ์งํํ์ต๋๋ค.
ํต์ฌ ๋ก์ง์ ๋ณ๊ฒฝ์ด ์์๊ธฐ ๋๋ฌธ์ ์ถ๊ฐ์ ์ธ ๊ณต์๊ฐ ๋ง์ด ๋ค์ด๊ฐ์ง ์์๊ณ , ํ์ฌ ๋ฌธ์ ์์ด ์ฌ์ฉ ์ค์
๋๋ค.
์ด ์ ๋๋ฉด ์๊ธฐ์ ๋ชฉ์ ์ ๋ฌ์ฑํด์ ๋ง์กฑ์ค๋ฝ๊ฒ ์ฌ์ฉํ ์ ์์ ๊ฒ ๊ฐ๋ค์.