yon11b

[토이 프로젝트] PDF 파일안의 텍스트를 문제별로 HWP에 삽입하기 본문

개발/프로젝트

[토이 프로젝트] PDF 파일안의 텍스트를 문제별로 HWP에 삽입하기

yon11b 2024. 10. 23. 18:41
반응형

문제해결 프로세스

 

처음에 생각한 문제해결 프로세스

  1. pdf 파일에서 문제별로 이미지를 추출해서 로컬에 저장
    • PDF->PNG변환 이유: PDF에서 바로 텍스트 추출보다 PNG에서 텍스트 추출이 더 쉬움
  2. 이미지 파일에서 텍스트 추출
  3. 추출한 텍스트를 합쳐서 하나의 txt 파일로 만듦
  4. txt에서 문제별로 추출하여 hwp에 입력

최종적으로 정해진 문제해결 프로세스

  1. pdf파일을 png 파일로 변환하여 저장
  2. png의 왼쪽, 오른쪽 다단을 위 아래로 합쳐서 새 png 파일로 저장
    • 이유: 이미지 파일에서 텍스트 변환을 하면, 위에서부터 아래로 읽는데, 원본 파일에서 문제가 다단 두 개로 나누어 배열 되어 있어서 아래와 같은 상황에서 1번→ 2번의 순서로 출력되는게 아니라 1→4→2→5 순서로 출력이 되어 버리기 때문.
    •   
  3. png 파일에서 텍스트 추출하기(naver clova ocr 기능 사용)
  4. 추출한 텍스트를 txt 파일에 저장
  5. txt 파일을 불러와서 hwp에 입력

 

결과

1. pdf파일을 png 파일로 변환하여 저장

png 위 아래 합치기 전 원본 상태

 

2. png의 왼쪽, 오른쪽 다단을 위 아래로 합쳐서 새 png 파일로 저장

png 위 아래 합친 후 상태 

3~5.  PNG 파일에서 텍스트 추출하기(naver clova ocr 기능 사용), HWP에 입력

추출한 텍스트와 hwp파일들

 

hwp 파일 내부

과정(파이썬 IDLE 출력 화면)

PDF 에서 PNG로 변환 후 TXT에 저장

 

TXT에서 문제 별로 텍스트 추출하여 HWP로 입력

 

HWP에 입력되는 모습

 

예외 처리

이 코드에서는 문제 구분을 번호.으로 하는데, 간혹가다가 OCR이 제대로 PNG 파일을 인식 못해서 .이 생략된 채로 TXT 파일에 저장될 때가 있다. 이런 경우, 코드는 6을 넘어서 아래까지 계속 탐색을 하다가 16.에서 조건을 만족시키고 16번 문제를 6번 문제가 들어가야 할 자리에 넣게 된다.

이 버그를 방지하기 위해 6번 문제 탐색 중에 6.이 발견되더라도 그 앞의 인덱스의 문자가 1이거나 2이면 삽입을 하지 않는 코드를 추가했다.

그리고 끝까지 다 탐색했는데도 6.을 발견하지 못한다면 "불러오지 못했으니 직접 문제를 작성해달라"는 알림메시지를 넣도록 했다.

 

6. 이 아니라 6 으로 불러와진 TXT
알림메시지

 

NAVER OCR 비용

 

general 요금제는 월 100건은 무료이고, 그 이상은 한 건에 3원이다. 그런데 또 처음 가입하면 10만원짜리 크레딧을 준다. 그래서 돈 안 내고 낭낭하게 쓸 수 있다.!!

 

1~4번 코드

# pdf 파일에 있는 내용을 txt 파일에 입력하는 코드
# 완성
# 2024.10.25
# =====================[프로세스]========================
# 1. pdf => png
# 2. png의 왼쪽, 오른쪽 다단을 위 아래로 합쳐서 새 png 파일로저장
# 3. png의 텍스트를 네이버 clover ocr을 사용하여 텍스로 변환 후 txt 파일에 저장
# ====================================================

import requests
import uuid
import time
import json
from PIL import Image
import fitz
import os

# 사용자로부터 키워드 입력받기
def input_file_name():
    keyword = input('파일 이름의 일부를 입력하세요: ')

    # 파일 리스트 가져오기
    files = os.listdir(PROBLEM_PATH)

    # 키워드를 포함한 파일 찾기
    matching_files = [file for file in files if keyword in file]
    return matching_files

PATH=''
PROBLEM_PATH=os.path.join(PATH, '문제파일')
matching_files = input_file_name()

# 결과 출력
if matching_files:
    print("찾은 파일:")
    for file in matching_files:
        print(file)
        if len(matching_files) == 1:            
            PDF_FILE_PATH=os.path.join(PROBLEM_PATH, file)
            FILE_NAME = file
        else:
            matching_files = input_file_name()
else:
    print("파일을 찾을 수 없습니다.")

page=0
# 1. pdf파일을 png 파일로 변환하여 저장
print('PDF 파일 읽는 중...')
doc = fitz.open(PDF_FILE_PATH)
input_dir = PATH + 'input_image\\'
for i, page in enumerate(doc):
    img = page.get_pixmap()
    img.save(os.path.join(input_dir, f'{i}_{FILE_NAME}.png'))
    page=i
print('page: ',page)
# 추출한 텍스트 저장할 txt 파일 생성
text_dir = os.path.join(PATH, f'text\\{FILE_NAME}.txt')
# UTF-8 인코딩으로 파일 열기 및 작성
f = open(text_dir, "w", encoding="utf-8") 
output_dir=PATH + 'output_image\\'

# 2. png 파일을 다단 두 개로 나누어 저장
# 이미지 파일 열기
print('이미지를 텍스트로 변환  중...')
for i in range(page):
    image_path = os.path.join(input_dir, f'{i}_{FILE_NAME}.png') # 원본 이미지 파일 경로
    image = Image.open(image_path)

    # 이미지 크기 가져오기
    width, height = image.size

    # 이미지 절반으로 나누기
    left_image = image.crop((0, 0, width // 2, height))  # 왼쪽 절반
    right_image = image.crop((width // 2, 0, width, height))  # 오른쪽 절반

    # 새로운 이미지 생성 (왼쪽 이미지 높이 + 오른쪽 이미지 높이)
    new_image = Image.new('RGB', (width // 2, height * 2))

    # 왼쪽 이미지 붙여넣기
    new_image.paste(left_image, (0, 0))
    # 오른쪽 이미지 붙여넣기
    new_image.paste(right_image, (0, height))

    # 결과 이미지 저장
    new_image.save(os.path.join(output_dir, f'{i}_{FILE_NAME}.png'))  # 결과 파일 경로

    # 3. png 파일에서 텍스트 추출하기(네이버 클로버 ocr)
    api_url = ''
    secret_key = ''
    image_file = os.path.join(output_dir, f'{i}_{FILE_NAME}.png')

    request_json = {
        'images': [
            {
                'format': 'png',
                'name': 'demo'
            }
        ],
        'requestId': str(uuid.uuid4()),
        'version': 'V2',
        'timestamp': int(round(time.time() * 1000))
    }
    payload = {'message': json.dumps(request_json).encode('UTF-8')}
    files = [
      ('file', open(image_file,'rb'))
    ]
    headers = {
      'X-OCR-SECRET': secret_key
    }
    response = requests.request("POST", api_url, headers=headers, data = payload, files = files)
    '''
    result = response.text.encode('utf8')
    result_json = json.loads(result.decode('utf8').replace("'", '"'))
    result_text = result_json['images'][0]['fields'][0]['inferText']
    print(result_text)
    '''

    print(f'{i+1} 페이지 완료...')
    # 4. 추출한 텍스트를 txt 파일에 저장
    for i in response.json()['images'][0]['fields']:
        text = i['inferText']
        f.write(text+' ')
f.close()

 

5번 코드 및 전체 코드는 github에서 확인해주세요.

https://github.com/yon11b/pdftohwp

 

GitHub - yon11b/pdftohwp: pdf의 텍스트를 hwp에 자동 입력되도록 하는 코드.

pdf의 텍스트를 hwp에 자동 입력되도록 하는 코드. Contribute to yon11b/pdftohwp development by creating an account on GitHub.

github.com

 

728x90