PYTHON 한글자동화

[ 한글 자동화 ] 파이썬으로 한글(HWP) 문서 선택 영역 텍스트 추출하기

나루하루001 2025. 6. 8. 15:05
반응형



한글 OLE Automation 소개


한글(HWP)은 OLE Automation을 통해 외부 프로그램에서 제어할 수 있는 기능을 제공합니다.
OLE Automation은 한 프로그램이 다른 프로그램을 제어할 수 있게 해주는 기술로, 이를 통해 파이썬에서 한글 문서를 열고, 읽고, 편집하는 등의 작업이 가능합니다.

한글의 OLE Automation은 다양한 객체와 메서드를 제공하며,

이 중에서 오늘은 실행 중인 한글 프로그램에 연결하여 문서의 텍스트를 추출하는 방법을 알아보겠습니다.

💡 알아두세요!
한글 OLE Automation을 사용하려면 한글 프로그램이 컴퓨터에 설치되어 있어야 합니다. 또한 이 기능은 Windows 환경에서만 동작합니다.

 

필요한 라이브러리


파이썬에서 한글 OLE Automation을 사용하기 위해 다음 라이브러리들이 필요합니다:

import sys
import pythoncom
import win32com.client as win32
from PySide6.QtWidgets import QApplication, QWidget

 

각 라이브러리의 역할은 다음과 같습니다:
- pythoncom: Windows COM(Component Object Model) 인터페이스를 사용하기 위한 라이브러리
- win32com.client: Windows COM 객체를 파이썬에서 쉽게 사용할 수 있게 해주는 라이브러리
- PySide6: Qt 기반의 GUI 라이브러리로, 사용자 인터페이스를 구현하는 데 사용

 

라이브러리 설치

 

필요한 라이브러리는 pip를 사용하여 설치할 수 있습니다:

pip install pywin32 pythoncom PySide6

 

실행 중인 한글 연결하기


먼저 실행 중인 한글 프로그램에 연결하는 방법을 알아보겠습니다.
이 기능은 `get_running_hwp()` 메서드에 구현되어 있습니다:

def get_running_hwp(self):
    """실행 중인 한글 프로그램 중 가장 최근 인스턴스를 반환"""
    try:
        context = pythoncom.CreateBindCtx(0)
        running_coms = pythoncom.GetRunningObjectTable()
        monikers = running_coms.EnumRunning()

        max_value = -1
        result_moniker = None

        for moniker in monikers:
            try:
                name = moniker.GetDisplayName(context, moniker)
                
                if name and name.startswith("!HwpObject"):
                    parts = name.split(".")
                    if len(parts) > 0:
                        number = int(parts[-1])
                        if number > max_value:
                            max_value = number
                            result_moniker = moniker
            except (ValueError, IndexError, pythoncom.com_error):
                continue

        if result_moniker:
            hwp_object = running_coms.GetObject(result_moniker)
            hwp_dispatch = hwp_object.QueryInterface(pythoncom.IID_IDispatch)
            return win32.Dispatch(hwp_dispatch)

    except Exception:
        return None
    
    return None

이 코드는 다음과 같은 작업을 수행합니다:
1. Windows의 실행 중인 객체 테이블(ROT)에 접근
2. 실행 중인 모든 COM 객체를 열거
3. 이름이 "!HwpObject"로 시작하는 객체를 찾음
4. 여러 한글 인스턴스가 실행 중인 경우 가장 최근에 실행된 인스턴스를 선택
5. 찾은 객체를 파이썬에서 사용할 수 있는 형태로 변환하여 반환

💡 참고
이 방법은 이미 실행 중인 한글 프로그램에 연결하는 방식입니다. 새로운 한글 인스턴스를 생성하려면 win32.gencache.EnsureDispatch("HWPFrame.HwpObject")와 같은 코드를 사용할 수 있습니다.

 

반응형

텍스트 추출 기능 구현


이제 실행 중인 한글 문서에서 텍스트를 추출하는 핵심 기능을 살펴보겠습니다.
이 기능은 `get_text()` 메서드에 구현되어 있습니다:

def get_text(self):
    """버튼 클릭시 선택된 텍스트 가져와서 라벨에 표시"""
    hwp = self.get_running_hwp()
    
    if not hwp:
        self.ui.label.setText("한글 프로그램을 찾을 수 없습니다")
        return
    
    try:
        hwp.InitScan(0x01, 0x00ff)
        all_text = []
        
        while True:
            result = hwp.GetText()
            status_code = result[0]  # 상태코드
            text = result[1]        # 실제 텍스트
            
            if status_code == 0:  # 더 이상 텍스트가 없음
                break
                
            all_text.append(text)
        
        hwp.ReleaseScan()
        
        # 모든 텍스트를 합치기
        final_text = "".join(all_text)
        self.ui.label.setText(final_text if final_text else "선택된 텍스트가 없습니다")
        
    except Exception as e:
        self.ui.label.setText(f"오류: {str(e)}")

 

get_text() 함수의 동작 원리

 

이 함수는 다음과 같은 단계로 텍스트를 추출합니다:
1. 한글 연결 확인: 먼저 `get_running_hwp()` 함수를 호출하여 실행 중인 한글 프로그램에 연결합니다.
2. 스캔 초기화: `InitScan()` 메서드를 호출하여 문서 검색을 위한 준비 작업을 수행합니다.
- 첫 번째 매개변수 `0x01`은 검색 대상을 지정하는 옵션으로, 여기서는 문자 타입 컨트롤(char type control)을 대상으로 합니다.
- 두 번째 매개변수 `0x00ff`는 검색 범위를 지정하는 옵션으로, 여기서는 블록으로 선택된 범위 내에서 검색하도록 설정합니다.
3. 텍스트 추출 루프: `while` 루프를 통해 `GetText()` 메서드를 반복 호출하여 문서의 텍스트를 순차적으로 추출합니다.
- `GetText()` 메서드는 상태 코드와 텍스트를 포함하는 결과를 반환합니다.
- 상태 코드가 0이면 더 이상 텍스트가 없음을 의미하므로 루프를 종료합니다.
- 추출된 텍스트는 `all_text` 리스트에 추가됩니다.
4. 스캔 해제: `ReleaseScan()` 메서드를 호출하여 `InitScan()`으로 설정된 정보를 초기화합니다.
5. 결과 표시: 추출된 모든 텍스트를 하나의 문자열로 합쳐 UI 라벨에 표시합니다.

💡 중요 포인트
한글 문서 검색 과정은 다음과 같은 순서로 진행됩니다:
1. InitScan()으로 검색을 위한 준비 작업 수행
2. GetText()를 호출하여 텍스트 추출
3. GetText()를 반복 호출하여 추가 텍스트 추출
4. ReleaseScan()을 호출하여 관련 정보 초기화

이 순서를 지키지 않으면 메모리 누수나 예기치 않은 동작이 발생할 수 있습니다.

InitScan 메서드의 매개변수

 

`InitScan()` 메서드는 문서 검색을 위한 중요한 설정을 담당합니다.

첫 번째 매개변수는 검색 대상을, 두 번째 매개변수는 검색 범위를 지정합니다.


첫 번째 매개변수 (option):
- `0x00` (maskNormal): 본문을 대상으로 검색 (서브리스트 제외)
- `0x01` (maskChar): char 타입 컨트롤 마스크 대상 (강제줄나눔, 문단끝, 하이픈 등)
- `0x02` (maskInline): inline 타입 컨트롤 마스크 대상 (누름틀 필드 끝 등)
- `0x04` (maskCtrl): extended 타입 컨트롤 마스크 대상 (바탕쪽, 머리말, 꼬리말 등)


두 번째 매개변수 (range):
- `0x0070` (scanSposDocument): 문서의 시작부터 (시작 위치)
- `0x0007` (scanEposDocument): 문서의 끝까지 (끝 위치)
- `0x00ff` (scanWithinSelection): 검색의 범위를 블록으로 제한
- `0x0000` (scanForward): 정방향 검색
- `0x0100` (scanBackward): 역방향 검색

 

GetText 메서드의 반환 값

 

`GetText()` 메서드는 상태 코드와 텍스트를 포함하는 결과를 반환합니다. 상태 코드는 다음과 같은 의미를 가집니다:
- `0`: 텍스트 정보 없음
- `1`: 리스트의 끝
- `2`: 일반 텍스트
- `3`: 다음 문단
- `4`: 제어문자 내부로 들어감
- `5`: 제어 문자를 빠져 나옴
- `101`: 초기화 안됨 (InitScan() 실패 또는 실행하지 않음)
- `102`: 텍스트 변환 실패

전체 코드


다음은 한글 문서에서 텍스트를 추출하는 전체 코드입니다:

# -*- coding: utf-8 -*-
import sys
import pythoncom
import win32com.client as win32
from PySide6.QtWidgets import QApplication, QWidget
from read_hwp_ui import Ui_Form

class HwpReaderApp(QWidget):
    def __init__(self):
        super().__init__()
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        
        # 라벨 글자 색을 흰색으로 설정
        self.ui.label.setStyleSheet("color: white;")
        
        # 버튼 클릭 이벤트 연결
        self.ui.pushButton.clicked.connect(self.get_text)
        
    def get_running_hwp(self):
        """실행 중인 한글 프로그램 중 가장 최근 인스턴스를 반환"""
        try:
            context = pythoncom.CreateBindCtx(0)
            running_coms = pythoncom.GetRunningObjectTable()
            monikers = running_coms.EnumRunning()

            max_value = -1
            result_moniker = None

            for moniker in monikers:
                try:
                    name = moniker.GetDisplayName(context, moniker)
                    
                    if name and name.startswith("!HwpObject"):
                        parts = name.split(".")
                        if len(parts) > 0:
                            number = int(parts[-1])
                            if number > max_value:
                                max_value = number
                                result_moniker = moniker
                except (ValueError, IndexError, pythoncom.com_error):
                    continue

            if result_moniker:
                hwp_object = running_coms.GetObject(result_moniker)
                hwp_dispatch = hwp_object.QueryInterface(pythoncom.IID_IDispatch)
                return win32.Dispatch(hwp_dispatch)

        except Exception:
            return None
        
        return None
    
    def get_text(self):
        """버튼 클릭시 선택된 텍스트 가져와서 라벨에 표시"""
        hwp = self.get_running_hwp()
        
        if not hwp:
            self.ui.label.setText("한글 프로그램을 찾을 수 없습니다")
            return
        
        try:
            hwp.InitScan(0x01, 0x00ff)
            all_text = []
            
            while True:
                result = hwp.GetText()
                status_code = result[0]  # 상태코드
                text = result[1]        # 실제 텍스트
                
                if status_code == 0:  # 더 이상 텍스트가 없음
                    break
                    
                all_text.append(text)
            
            hwp.ReleaseScan()
            
            # 모든 텍스트를 합치기
            final_text = "".join(all_text)
            self.ui.label.setText(final_text if final_text else "선택된 텍스트가 없습니다")
            
        except Exception as e:
            self.ui.label.setText(f"오류: {str(e)}")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    
    window = HwpReaderApp()
    window.show()
    
    sys.exit(app.exec())

 

실행결과 

 

 

결론


이 글에서는 파이썬을 사용하여 실행 중인 한글 프로그램에 연결하고,

문서의 텍스트를 추출하는 방법을 알아보았습니다.


한글의 OLE Automation 기능을 활용하면 다양한 작업을 자동화할 수 있습니다:
- 문서 열기, 저장, 닫기
- 텍스트 추출 및 삽입
- 서식 변경
- 표, 이미지 등 다양한 객체 조작
- 필드 데이터 처리


특히 `get_text()` 함수는 한글 문서의 텍스트를 추출하는 핵심 기능을 담당하며,

`InitScan()`, `GetText()`, `ReleaseScan()` 메서드를 올바른 순서로 사용하는 것이 중요합니다.


이 코드를 기반으로 한글 문서 자동화 작업을 더욱 확장할 수 있으며, 업무 프로세스 자동화나 문서 처리 시스템 구축 등에 활용할 수 있습니다.

 

이번 블로그는 한글 자동화를 중점으로 다루었기 때문에

별도 Pyside6의 문법에 대해서는 다루지 않았습니다.

[ 파이썬 관련 블로그 글 목록 ] 

파이썬(Python) 블로그 목록
반응형