문서를 PDF로 스캔하고 그 스캔파일의 텍스트가 필요할 때,
엑셀 파일의 시트를 순환하면서 모든 텍스트를 불러올때,
텍스트 변환 전문 프로그램(알 PDF, 아크로뱃 등)도 있지만 회사에서는 유료이기 때문에그냥 한번 만들어봤다.(물론 커서 AI를 활용해서.ㅎㅎ)
예전에 엑셀 고수들이 필요한 함수를 만들어서 쓴다고 했는데.
AI가 나온 지금 내가 필요한 프로그램을 만들어서 쓸 수 있을 정도는 되어야
"GPT좀 쓰네" 라는 말을 들을 수 있지 않을까 싶다.ㅎ
아무튼,
AI를 활용해서 코딩을 하다 보니
과거에는 엄두도 못 냈던 것 들도 이제는 단순히 아이디어만 가지고도 GPT를 괴롭히면서 하나씩 만들어보고 있다.😁
혹시라도 이 글을 보시는 분들께 도움이 될까 해서
내가 만든(?) 프로그램 코드를 공유해 본다.
프로그램의 주요 기능은 다음과 같다.
- PDF 및 엑셀 파일의 텍스트 변환 기능 : OCR(광학 문자 인식) 기능을 포함해 텍스트를 자동 추출할 수 있다.
- 불필요한 문자 제거 : 특수문자, 공백 줄, 다중 공백 등을 깔끔하게 정리한다.
- 텍스트 검색 기능 : 추출한 텍스트에서 특정 단어를 빠르게 검색할 수 있다.
- OCR기능을 위해 Tesseract 프로그램을 설치해야 한다.

import tkinter as tk
from tkinter import filedialog, ttk
import os
import re
import pytesseract
from PIL import Image, ImageFilter
import fitz
import sys
import openpyxl # openpyxl 라이브러리 추가
import xlrd # xlrd 라이브러리 추가
def get_tesseract_path():
try:
if getattr(sys, 'frozen', False):
# PyInstaller로 실행 파일 생성 시
base_path = sys._MEIPASS
else:
base_path = os.path.dirname(os.path.abspath(__file__))
tesseract_path = os.path.join(base_path, 'Tesseract-OCR', 'tesseract.exe')
if os.path.exists(tesseract_path):
return tesseract_path
# 기본 설치 경로 확인
program_files = os.environ.get('ProgramFiles', 'C:/Program Files')
tesseract_path = os.path.join(program_files, 'Tesseract-OCR', 'tesseract.exe')
if os.path.exists(tesseract_path):
return tesseract_path
except Exception as e:
print(f"Tesseract 경로 찾기 실패: {e}")
return r'C:\Program Files\Tesseract-OCR\tesseract.exe'
pytesseract.pytesseract.tesseract_cmd = get_tesseract_path()
class PDFTextExtractor:
def __init__(self):
self.window = tk.Tk()
self.window.title("PDF 및 엑셀 텍스트 추출기")
self.window.geometry("600x400")
# Tesseract 경로 확인
if not os.path.exists(r'C:\Program Files\Tesseract-OCR\tesseract.exe'):
self.display_message("Tesseract 설치가 필요합니다. 설치파일을 다운로드 받아서 설치하세요.")
self.open_install_link()
# 파일 경로 프레임
path_frame = ttk.Frame(self.window)
path_frame.pack(pady=10, padx=10, fill="x")
self.path_var = tk.StringVar()
path_entry = ttk.Entry(path_frame, textvariable=self.path_var, width=30)
path_entry.pack(side="left", padx=(0, 5))
browse_btn = ttk.Button(path_frame, text="파일 선택", command=self.browse_file)
browse_btn.pack(side="left", padx=(0, 5))
clear_btn = ttk.Button(path_frame, text="지우기", command=self.clear_all)
clear_btn.pack(side="left")
# 텍스트 출력 영역과 버튼을 포함할 메인 프레임
main_frame = ttk.Frame(self.window)
main_frame.pack(pady=10, padx=10, fill="both", expand=True)
# 텍스트 영역 프레임 (왼쪽)
text_frame = ttk.Frame(main_frame)
text_frame.pack(side="left", fill="both", expand=True)
self.text_area = tk.Text(text_frame, height=15, width=60, wrap=tk.WORD)
self.text_area.pack(side="left", fill="both", expand=True)
# 스크롤바 추가
scrollbar = ttk.Scrollbar(text_frame, orient="vertical", command=self.text_area.yview)
scrollbar.pack(side="right", fill="y")
self.text_area.configure(yscrollcommand=scrollbar.set)
# 버튼 프레임 (오른쪽)
btn_frame = ttk.Frame(main_frame)
btn_frame.pack(side="right", fill="y", padx=(10, 0))
# 버튼들을 리스트로 생성
buttons = [
("텍스트 추출", self.extract_text_from_file),
("텍스트 저장", self.save_text),
("특수문자 제거", self.remove_special_chars),
("공백라인 제거", self.remove_empty_lines),
("다중공백 제거", self.reduce_multiple_spaces),
("원본으로 되돌리기", self.restore_original_text)
]
# 버튼 생성 및 세로로 배치
for text, command in buttons:
btn = ttk.Button(btn_frame, text=text, command=command)
btn.pack(pady=2, fill="x")
# 원본 텍스트를 저장할 변수 추가
self.original_text = ""
# 검색 프레임 추가
search_frame = ttk.Frame(self.window)
search_frame.pack(pady=5, padx=10, fill="x")
self.search_var = tk.StringVar()
search_entry = ttk.Entry(search_frame, textvariable=self.search_var, width=30)
search_entry.pack(side="left", padx=(0, 5))
find_btn = ttk.Button(search_frame, text="찾기", command=self.find_text)
find_btn.pack(side="left", padx=2)
prev_btn = ttk.Button(search_frame, text="↑", command=lambda: self.navigate_search("prev"))
prev_btn.pack(side="left", padx=2)
next_btn = ttk.Button(search_frame, text="↓", command=lambda: self.navigate_search("next"))
next_btn.pack(side="left", padx=2)
# 검색 결과 저장을 위한 변수들
self.search_positions = []
self.current_search_index = -1
# 설치 링크 버튼 추가
install_frame = ttk.Frame(self.window)
install_frame.pack(pady=5, padx=10, fill="x")
install_btn = ttk.Button(install_frame, text="Tesseract 설치하기", command=self.open_install_link)
install_btn.pack(side="left", padx=(0, 5))
def browse_file(self):
filename = filedialog.askopenfilename(
filetypes=[("All files", "*.*")]
)
if filename:
self.path_var.set(filename)
def extract_text(self):
pdf_path = self.path_var.get()
if not pdf_path:
self.display_message("파일을 선택해주세요.")
return
try:
text = self.extract_text_from_pdf(pdf_path)
if len(text.strip()) < 100: # 텍스트가 100자 미만인 경우
#print("일반 텍스트 추출 실패, OCR 시도 중...")
text = self.extract_text_with_ocr(pdf_path)
self.display_text(text)
except Exception as e:
self.display_message(f"오류 발생: {str(e)}")
def extract_text_from_pdf(self, pdf_path):
"""PDF에서 텍스트를 추출하는 함수"""
doc = fitz.open(pdf_path)
text = ""
for page in doc:
page_text = page.get_text("text")
text += page_text + "\n"
doc.close()
return text
def extract_text_with_ocr(self, pdf_path):
"""OCR을 사용하여 PDF에서 텍스트를 추출하는 함수"""
doc = fitz.open(pdf_path)
text = ""
for page_num in range(len(doc)):
page = doc[page_num]
img = self.get_page_image(page)
# 이미지 전처리: 노이즈 제거 및 대비 증가
img = img.convert('L') # 그레이스케일 변환
img = img.filter(ImageFilter.MedianFilter()) # 노이즈 제거
img = img.point(lambda x: 0 if x < 140 else 255, '1') # 이진화
# OCR 수행 (한국어 + 영어)
text += pytesseract.image_to_string(
img,
lang='kor+eng',
config='--psm 3 --oem 1'
) + "\n"
doc.close()
return text
def get_page_image(self, page):
"""페이지 이미지를 가져오는 함수"""
zoom = 3 # 해상도를 높이기 위해 값을 증가시킴
mat = fitz.Matrix(zoom, zoom)
pix = page.get_pixmap(matrix=mat)
img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
return img
def display_text(self, text):
"""텍스트를 텍스트 영역에 표시하는 함수"""
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, text)
def display_message(self, message):
"""메시지를 텍스트 영역에 표시하는 함수"""
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, message)
def save_text(self):
text = self.text_area.get(1.0, tk.END)
if not text.strip():
return
filename = filedialog.asksaveasfilename(
defaultextension=".txt",
filetypes=[("Text files", "*.txt")]
)
if filename:
with open(filename, 'w', encoding='utf-8') as file:
file.write(text)
def remove_special_chars(self):
text = self.text_area.get(1.0, tk.END)
if not text.strip():
return
# 특수문자 제거 전에 원본 텍스트 저장
self.original_text = text
# 특수문자 제거 (알파벳, 숫자, 한글, 공백만 남김)
cleaned_text = re.sub(r'[^a-zA-Z0-9가-힣\s]', '', text)
# 결과 텍스트 출력
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, cleaned_text)
def restore_original_text(self):
if self.original_text:
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, self.original_text)
def find_text(self):
search_term = self.search_var.get()
if not search_term:
return
self.search_positions = []
self.current_search_index = -1
text_content = self.text_area.get("1.0", tk.END)
start_pos = "1.0"
while True:
start_pos = self.text_area.search(search_term, start_pos, tk.END)
if not start_pos:
break
end_pos = f"{start_pos}+{len(search_term)}c"
self.search_positions.append(start_pos)
start_pos = end_pos
if self.search_positions:
self.current_search_index = 0
self.highlight_current_search()
def navigate_search(self, direction):
if not self.search_positions:
return
if direction == "next":
self.current_search_index = (self.current_search_index + 1) % len(self.search_positions)
else:
self.current_search_index = (self.current_search_index - 1) % len(self.search_positions)
self.highlight_current_search()
def highlight_current_search(self):
# 모든 하이라이트 제거
self.text_area.tag_remove("search", "1.0", tk.END)
if self.search_positions:
# 현재 검색 위치 하이라이트
pos = self.search_positions[self.current_search_index]
end_pos = f"{pos}+{len(self.search_var.get())}c"
self.text_area.tag_add("search", pos, end_pos)
self.text_area.tag_config("search", background="yellow")
# 검색된 위치로 스크롤
self.text_area.see(pos)
def extract_text_ocr(self):
pdf_path = self.path_var.get()
if not pdf_path:
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, "PDF 파일을 선택해주세요.")
return
try:
doc = fitz.open(pdf_path)
text = ""
for page_num in range(len(doc)):
page = doc[page_num]
# 해상도 향상
zoom = 3 # 해상도를 높이기 위해 값을 증가시킴
mat = fitz.Matrix(zoom, zoom)
pix = page.get_pixmap(matrix=mat)
img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
# 이미지 전처리
img = img.convert('L') # 그레이스케일 변환
img = img.point(lambda x: 0 if x < 128 else 255, '1') # 이진화
# OCR 수행 (한국어)
text += pytesseract.image_to_string(img, lang='kor+eng', config='--psm 6') + "\n"
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, text)
doc.close()
except Exception as e:
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, f"OCR 오류 발생: {str(e)}")
def remove_empty_lines(self):
text = self.text_area.get(1.0, tk.END)
if not text.strip():
return
# 원본 텍스트 저장
self.original_text = text
# 빈 줄 제거
cleaned_text = '\n'.join([line for line in text.splitlines() if line.strip()])
# 결과 텍스트 출력
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, cleaned_text)
def clear_all(self):
"""파스트 영역만 지우는 함수"""
self.text_area.delete(1.0, tk.END) # 텍스트 영역 지우기
self.original_text = "" # 원본 텍스트 초기화
self.search_positions = [] # 검색 결과 초기화
self.current_search_index = -1 # 검색 인덱스 초기화
def run(self):
self.window.mainloop()
def reduce_multiple_spaces(self):
text = self.text_area.get(1.0, tk.END)
if not text.strip():
return
# 원본 텍스트 저장
self.original_text = text
# 연속된 공백을 하나의 공백으로 변경
cleaned_text = re.sub(r'\s{4,}', ' ', text)
# 결과 텍스트 출력
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, cleaned_text)
def open_install_link(self):
import webbrowser
webbrowser.open("https://github.com/tesseract-ocr/tesseract/releases") # Tesseract 설치 링크
def extract_text_from_excel(self):
"""엑셀 파일에서 모든 시트의 셀 텍스트를 추출하는 함수"""
excel_path = self.path_var.get()
if not excel_path:
self.display_message("엑셀 파일을 선택해주세요.")
return
try:
text = ""
if excel_path.endswith('.xls'):
# .xls 파일 처리
workbook = xlrd.open_workbook(excel_path)
for sheet in workbook.sheets():
for row_idx in range(sheet.nrows):
row = sheet.row(row_idx)
row_text = " ".join([str(cell.value) for cell in row if cell.value is not None])
text += row_text + "\n"
elif excel_path.endswith('.xlsx') or excel_path.endswith('.xlsm'):
# .xlsx 및 .xlsm 파일 처리
workbook = openpyxl.load_workbook(excel_path, data_only=True)
for sheet in workbook.worksheets:
# 셀 텍스트 추출
for row in sheet.iter_rows(values_only=True):
row_text = " ".join([str(cell) for cell in row if cell is not None])
text += row_text + "\n"
# 도형의 텍스트 추출은 지원되지 않음
# 텍스트 박스의 텍스트 추출은 지원되지 않음
self.display_text(text)
except Exception as e:
self.display_message(f"엑셀 텍스트 추출 오류: {str(e)}")
def extract_text_from_file(self):
"""파일 유형에 따라 적절한 텍스트 추출 함수 호출"""
file_path = self.path_var.get()
if not file_path:
self.display_message("파일을 선택해주세요.")
return
if file_path.lower().endswith('.pdf'):
self.extract_text()
elif file_path.lower().endswith(('.xls', '.xlsx', '.xlsm')):
self.extract_text_from_excel()
else:
self.display_message("지원되지 않는 파일 형식입니다.")
if __name__ == "__main__":
app = PDFTextExtractor()
app.run()
import tkinter as tk
from tkinter import filedialog, ttk
import os
import re
import pytesseract
from PIL import Image, ImageFilter
import fitz
import sys
import openpyxl # openpyxl 라이브러리 추가
import xlrd # xlrd 라이브러리 추가
def get_tesseract_path():
try:
if getattr(sys, 'frozen', False):
# PyInstaller로 실행 파일 생성 시
base_path = sys._MEIPASS
else:
base_path = os.path.dirname(os.path.abspath(__file__))
tesseract_path = os.path.join(base_path, 'Tesseract-OCR', 'tesseract.exe')
if os.path.exists(tesseract_path):
return tesseract_path
# 기본 설치 경로 확인
program_files = os.environ.get('ProgramFiles', 'C:/Program Files')
tesseract_path = os.path.join(program_files, 'Tesseract-OCR', 'tesseract.exe')
if os.path.exists(tesseract_path):
return tesseract_path
except Exception as e:
print(f"Tesseract 경로 찾기 실패: {e}")
return r'C:\Program Files\Tesseract-OCR\tesseract.exe'
pytesseract.pytesseract.tesseract_cmd = get_tesseract_path()
class PDFTextExtractor:
def __init__(self):
self.window = tk.Tk()
self.window.title("PDF 및 엑셀 텍스트 추출기")
self.window.geometry("600x400")
# Tesseract 경로 확인
if not os.path.exists(r'C:\Program Files\Tesseract-OCR\tesseract.exe'):
self.display_message("Tesseract 설치가 필요합니다. 설치파일을 다운로드 받아서 설치하세요.")
self.open_install_link()
# 파일 경로 프레임
path_frame = ttk.Frame(self.window)
path_frame.pack(pady=10, padx=10, fill="x")
self.path_var = tk.StringVar()
path_entry = ttk.Entry(path_frame, textvariable=self.path_var, width=30)
path_entry.pack(side="left", padx=(0, 5))
browse_btn = ttk.Button(path_frame, text="파일 선택", command=self.browse_file)
browse_btn.pack(side="left", padx=(0, 5))
clear_btn = ttk.Button(path_frame, text="지우기", command=self.clear_all)
clear_btn.pack(side="left")
# 텍스트 출력 영역과 버튼을 포함할 메인 프레임
main_frame = ttk.Frame(self.window)
main_frame.pack(pady=10, padx=10, fill="both", expand=True)
# 텍스트 영역 프레임 (왼쪽)
text_frame = ttk.Frame(main_frame)
text_frame.pack(side="left", fill="both", expand=True)
self.text_area = tk.Text(text_frame, height=15, width=60, wrap=tk.WORD)
self.text_area.pack(side="left", fill="both", expand=True)
# 스크롤바 추가
scrollbar = ttk.Scrollbar(text_frame, orient="vertical", command=self.text_area.yview)
scrollbar.pack(side="right", fill="y")
self.text_area.configure(yscrollcommand=scrollbar.set)
# 버튼 프레임 (오른쪽)
btn_frame = ttk.Frame(main_frame)
btn_frame.pack(side="right", fill="y", padx=(10, 0))
# 버튼들을 리스트로 생성
buttons = [
("텍스트 추출", self.extract_text_from_file),
("텍스트 저장", self.save_text),
("특수문자 제거", self.remove_special_chars),
("공백라인 제거", self.remove_empty_lines),
("다중공백 제거", self.reduce_multiple_spaces),
("원본으로 되돌리기", self.restore_original_text)
]
# 버튼 생성 및 세로로 배치
for text, command in buttons:
btn = ttk.Button(btn_frame, text=text, command=command)
btn.pack(pady=2, fill="x")
# 원본 텍스트를 저장할 변수 추가
self.original_text = ""
# 검색 프레임 추가
search_frame = ttk.Frame(self.window)
search_frame.pack(pady=5, padx=10, fill="x")
self.search_var = tk.StringVar()
search_entry = ttk.Entry(search_frame, textvariable=self.search_var, width=30)
search_entry.pack(side="left", padx=(0, 5))
find_btn = ttk.Button(search_frame, text="찾기", command=self.find_text)
find_btn.pack(side="left", padx=2)
prev_btn = ttk.Button(search_frame, text="↑", command=lambda: self.navigate_search("prev"))
prev_btn.pack(side="left", padx=2)
next_btn = ttk.Button(search_frame, text="↓", command=lambda: self.navigate_search("next"))
next_btn.pack(side="left", padx=2)
# 검색 결과 저장을 위한 변수들
self.search_positions = []
self.current_search_index = -1
# 설치 링크 버튼 추가
install_frame = ttk.Frame(self.window)
install_frame.pack(pady=5, padx=10, fill="x")
install_btn = ttk.Button(install_frame, text="Tesseract 설치하기", command=self.open_install_link)
install_btn.pack(side="left", padx=(0, 5))
def browse_file(self):
filename = filedialog.askopenfilename(
filetypes=[("All files", "*.*")]
)
if filename:
self.path_var.set(filename)
def extract_text(self):
pdf_path = self.path_var.get()
if not pdf_path:
self.display_message("파일을 선택해주세요.")
return
try:
text = self.extract_text_from_pdf(pdf_path)
if len(text.strip()) < 100: # 텍스트가 100자 미만인 경우
#print("일반 텍스트 추출 실패, OCR 시도 중...")
text = self.extract_text_with_ocr(pdf_path)
self.display_text(text)
except Exception as e:
self.display_message(f"오류 발생: {str(e)}")
def extract_text_from_pdf(self, pdf_path):
"""PDF에서 텍스트를 추출하는 함수"""
doc = fitz.open(pdf_path)
text = ""
for page in doc:
page_text = page.get_text("text")
text += page_text + "\n"
doc.close()
return text
def extract_text_with_ocr(self, pdf_path):
"""OCR을 사용하여 PDF에서 텍스트를 추출하는 함수"""
doc = fitz.open(pdf_path)
text = ""
for page_num in range(len(doc)):
page = doc[page_num]
img = self.get_page_image(page)
# 이미지 전처리: 노이즈 제거 및 대비 증가
img = img.convert('L') # 그레이스케일 변환
img = img.filter(ImageFilter.MedianFilter()) # 노이즈 제거
img = img.point(lambda x: 0 if x < 140 else 255, '1') # 이진화
# OCR 수행 (한국어 + 영어)
text += pytesseract.image_to_string(
img,
lang='kor+eng',
config='--psm 3 --oem 1'
) + "\n"
doc.close()
return text
def get_page_image(self, page):
"""페이지 이미지를 가져오는 함수"""
zoom = 3 # 해상도를 높이기 위해 값을 증가시킴
mat = fitz.Matrix(zoom, zoom)
pix = page.get_pixmap(matrix=mat)
img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
return img
def display_text(self, text):
"""텍스트를 텍스트 영역에 표시하는 함수"""
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, text)
def display_message(self, message):
"""메시지를 텍스트 영역에 표시하는 함수"""
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, message)
def save_text(self):
text = self.text_area.get(1.0, tk.END)
if not text.strip():
return
filename = filedialog.asksaveasfilename(
defaultextension=".txt",
filetypes=[("Text files", "*.txt")]
)
if filename:
with open(filename, 'w', encoding='utf-8') as file:
file.write(text)
def remove_special_chars(self):
text = self.text_area.get(1.0, tk.END)
if not text.strip():
return
# 특수문자 제거 전에 원본 텍스트 저장
self.original_text = text
# 특수문자 제거 (알파벳, 숫자, 한글, 공백만 남김)
cleaned_text = re.sub(r'[^a-zA-Z0-9가-힣\s]', '', text)
# 결과 텍스트 출력
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, cleaned_text)
def restore_original_text(self):
if self.original_text:
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, self.original_text)
def find_text(self):
search_term = self.search_var.get()
if not search_term:
return
self.search_positions = []
self.current_search_index = -1
text_content = self.text_area.get("1.0", tk.END)
start_pos = "1.0"
while True:
start_pos = self.text_area.search(search_term, start_pos, tk.END)
if not start_pos:
break
end_pos = f"{start_pos}+{len(search_term)}c"
self.search_positions.append(start_pos)
start_pos = end_pos
if self.search_positions:
self.current_search_index = 0
self.highlight_current_search()
def navigate_search(self, direction):
if not self.search_positions:
return
if direction == "next":
self.current_search_index = (self.current_search_index + 1) % len(self.search_positions)
else:
self.current_search_index = (self.current_search_index - 1) % len(self.search_positions)
self.highlight_current_search()
def highlight_current_search(self):
# 모든 하이라이트 제거
self.text_area.tag_remove("search", "1.0", tk.END)
if self.search_positions:
# 현재 검색 위치 하이라이트
pos = self.search_positions[self.current_search_index]
end_pos = f"{pos}+{len(self.search_var.get())}c"
self.text_area.tag_add("search", pos, end_pos)
self.text_area.tag_config("search", background="yellow")
# 검색된 위치로 스크롤
self.text_area.see(pos)
def extract_text_ocr(self):
pdf_path = self.path_var.get()
if not pdf_path:
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, "PDF 파일을 선택해주세요.")
return
try:
doc = fitz.open(pdf_path)
text = ""
for page_num in range(len(doc)):
page = doc[page_num]
# 해상도 향상
zoom = 3 # 해상도를 높이기 위해 값을 증가시킴
mat = fitz.Matrix(zoom, zoom)
pix = page.get_pixmap(matrix=mat)
img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
# 이미지 전처리
img = img.convert('L') # 그레이스케일 변환
img = img.point(lambda x: 0 if x < 128 else 255, '1') # 이진화
# OCR 수행 (한국어)
text += pytesseract.image_to_string(img, lang='kor+eng', config='--psm 6') + "\n"
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, text)
doc.close()
except Exception as e:
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, f"OCR 오류 발생: {str(e)}")
def remove_empty_lines(self):
text = self.text_area.get(1.0, tk.END)
if not text.strip():
return
# 원본 텍스트 저장
self.original_text = text
# 빈 줄 제거
cleaned_text = '\n'.join([line for line in text.splitlines() if line.strip()])
# 결과 텍스트 출력
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, cleaned_text)
def clear_all(self):
"""파스트 영역만 지우는 함수"""
self.text_area.delete(1.0, tk.END) # 텍스트 영역 지우기
self.original_text = "" # 원본 텍스트 초기화
self.search_positions = [] # 검색 결과 초기화
self.current_search_index = -1 # 검색 인덱스 초기화
def run(self):
self.window.mainloop()
def reduce_multiple_spaces(self):
text = self.text_area.get(1.0, tk.END)
if not text.strip():
return
# 원본 텍스트 저장
self.original_text = text
# 연속된 공백을 하나의 공백으로 변경
cleaned_text = re.sub(r'\s{4,}', ' ', text)
# 결과 텍스트 출력
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, cleaned_text)
def open_install_link(self):
import webbrowser
webbrowser.open("https://github.com/tesseract-ocr/tesseract/releases") # Tesseract 설치 링크
def extract_text_from_excel(self):
"""엑셀 파일에서 모든 시트의 셀 텍스트를 추출하는 함수"""
excel_path = self.path_var.get()
if not excel_path:
self.display_message("엑셀 파일을 선택해주세요.")
return
try:
text = ""
if excel_path.endswith('.xls'):
# .xls 파일 처리
workbook = xlrd.open_workbook(excel_path)
for sheet in workbook.sheets():
for row_idx in range(sheet.nrows):
row = sheet.row(row_idx)
row_text = " ".join([str(cell.value) for cell in row if cell.value is not None])
text += row_text + "\n"
elif excel_path.endswith('.xlsx') or excel_path.endswith('.xlsm'):
# .xlsx 및 .xlsm 파일 처리
workbook = openpyxl.load_workbook(excel_path, data_only=True)
for sheet in workbook.worksheets:
# 셀 텍스트 추출
for row in sheet.iter_rows(values_only=True):
row_text = " ".join([str(cell) for cell in row if cell is not None])
text += row_text + "\n"
# 도형의 텍스트 추출은 지원되지 않음
# 텍스트 박스의 텍스트 추출은 지원되지 않음
self.display_text(text)
except Exception as e:
self.display_message(f"엑셀 텍스트 추출 오류: {str(e)}")
def extract_text_from_file(self):
"""파일 유형에 따라 적절한 텍스트 추출 함수 호출"""
file_path = self.path_var.get()
if not file_path:
self.display_message("파일을 선택해주세요.")
return
if file_path.lower().endswith('.pdf'):
self.extract_text()
elif file_path.lower().endswith(('.xls', '.xlsx', '.xlsm')):
self.extract_text_from_excel()
else:
self.display_message("지원되지 않는 파일 형식입니다.")
if __name__ == "__main__":
app = PDFTextExtractor()
app.run()

'코딩 > 입코딩' 카테고리의 다른 글
[입코딩] 나만의 GPT 만들기 활용 - 연말정산 도우미 봇 제작 (1) | 2025.02.15 |
---|