본문 바로가기
아래아한글 자동화/python+hwp 중급

[5/8] 문서에서 제목 추출하기

by 일코 2022. 10. 25.

이전 포스팅까지는 이미지를 저장하는 프로세스를 구현해보았습니다.

이번 포스팅부터는 문단제목을 추출하는 작업을 해보겠습니다.

 

기본적으로 한/글 프로그램은 찾기/찾아바꾸기 기능이 잘 구현되어 있습니다.

매크로 추출을 해 보면, 다양한 옵션도 활용이 가능하고요.

그런데, 탐색한 문자열을 파이썬으로 추출해서 활용하려면 번거로운 추가작업이 필요합니다.

이를테면,

문단의 끝까지 추가선택한 후, 복사해서 클립보드로 옮기고

파이썬으로 클립보드의 문자열을 추출해야 한다든지요.

번거롭습니다.

 

그런데 한/글에서는 이런 일련의 과정을 간결하게 덜어주는 

GetText라는 메서드가 존재합니다.

GetText, 한/글 자동화 고급과정의 첫걸음① (tistory.com)

 

GetText, 한/글 자동화 고급과정의 첫걸음①

안녕하세요? 일상의 코딩, 일코입니다. 이전 포스팅에서 찾기 후 매크로 몇 줄을 보태서 문제를 간단히 해결했습니다. 2022.02.03 - [업무자동화/파이썬-아래아한글 자동화 기초] - 찾기로 탐색한 단

martinii.fun

 

hwp.GetText는 찾아바꾸기와는 많이 다르고, 좀 독특하기도 해서

익숙해지려면 여러 번 사용해봐야 합니다.

 

hwp.GetText의 기본적인 사용법은

 

1. hwp.InitScan()으로 탐색옵션을 설정하고

2. hwp.GetText()를 반복실행하면서 줄바꿈 단위로 문자열과 상태값을 리턴받다가

3. hwp.ReleaseScan()으로 탐색 종료

하는 방식입니다.

 

이해를 돕기 위해 

이해를 돕기 위해 아주 간단한 코드를 실행해보겠습니다.

보시다시피 문자열이 바로바로 리턴되므로 별도의 작업 없이 바로 파이썬에서 가공이 가능합니다.

특히, 상태값(정수)을 통해 얻을 수 있는 정보도 있는데, 예를 들면 4는 "표에 진입", 5는 "표 빠져나옴" 등입니다.

 

 

GetText를 활용해서 아래의 코드를 한 번 실행해보겠습니다.

hwp.InitScan(option=0, Range=0x77)  # 0:본문만을 대상으로, 0x77:문서의 시작부터 문서의 끝까지

state = 0  # 상태값 변수 초기화
while state != 1:  # 문서 끝에 도달하기 전까지 반복해서
    state, text = hwp.GetText()  # 줄바꿈 단위로 탐색함
    if text.startswith("□ "):  # 탐색결과가 "□ "으로 시작하면
        print(f"문단제목 : {text[1:].strip()}")  # 글머리기호 제거
        hwp.MovePos(201)  # 해당 위치로 캐럿을 옮겨서
        print(f"문단번호 : {hwp.GetPos()[1]}\n")
hwp.ReleaseScan()  # 탐색 종료

<부연설명>

[3번 라인]
"state = 0"은 while문에 state를 활용하기 위해 넣은 코드임

[7번 라인]
text == "□ 나무사진\n"
text[1:] == " 나무사진\n"
text[1:].strip() == "나무사진"

[9번 라인]
hwp.GetPos() == (0, 2, 0)  # == (구역번호, 문단번호, 글자순서)
hwp.GetPos()[1] == 2  # 문단번호만 사용

 

다소 설명이 부족한 듯 하지만,

문단번호와 문단제목을 추출했으니

이제 함수를 하나 정의해줍니다.

아래 함수는 두 가지를 리턴해주는데,

하나는 제목 리스트,

그리고 다른 하나는,

특정 줄번호(정수값)을 받으면

해당하는 제목 문자열을 리턴해주는 "함수"입니다.

def 제목뽑기():
    """
    빈 네모(□) 글머리기호로 시작하는 제목의
    텍스트와 줄번호를 추출한 후에
    이를 통해 해당 구간의 제목을 리턴하는 함수를 만들고
    그 함수를 리턴함

    <예시>
    title_list = ['나무사진', '꽃사진', '풀사진']
    range_list = [2, 5, 8]
    title_dict = {range(2, 5): '나무사진', range(5, 8): '꽃사진', 8: '풀사진'}

    title_func(4) => "나무사진"
    title_func(5) => "꽃사진"
    title_func(9) => "풀사진"
    """
    
    hwp.InitScan(option=0, Range=0x77)  # 0:본문을 대상으로, 0x77:문서의 시작부터 문서의 끝까지
    state = 0  # state 변수 초기화
    title_list = []  # 제목 담을 리스트
    range_list = []  # 제목라인의 줄번호 담을 리스트
    while state != 1:  # 문서 끝에 도달하기 전까지 반복해서
        state, text = hwp.GetText()  # 한 줄(줄바꿈)씩 탐색함
        if text.startswith("□ "):  # 탐색결과가 "□ "으로 시작하면
            title_list.append(text[1:].strip())  # 글머리 빼고 title_list에 추가한 후
            hwp.MovePos(201)  # 해당 위치로 이동해서
            range_list.append(hwp.GetPos()[1])  # 줄번호 추출해서 range_list에 추가
    hwp.ReleaseScan()  # 탐색 종료
    
    title_dict = {}
    for idx, title in enumerate(title_list):
        try:
            title_dict[range(range_list[idx], range_list[idx+1])] = title
        except IndexError:
            title_dict[range_list[idx]] = title

    def title_func(num):  # num == 줄번호
        for i in title_dict.keys():
            if num < list(title_dict.keys())[-1]:
                if num in i:
                    return title_dict[i]
            else:
                return title_dict[list(title_dict.keys())[-1]]

    return title_list, title_func

 

제 역량이 미천하여 함수가 다소 더럽고 냄새가 날 수 있습니다..

함수 주석의 <예시>를 읽어보시면 위 함수를 이해하는 데 도움이 될 것입니다.

위 코드를 실행해보겠습니다.

 

참고로, 제목함수 안에 들어가는 정수는 줄번호(0부터 시작)입니다.

 

이번 포스팅은 여기서 끊고

다음 포스팅에서 이어서 설명드리겠습니다.

 

 

1. 문단제목과 위치를 추출해서

2. 하위폴더를 만들어 두고

3. 각 이미지가 어느 문단에 속해 있는지 파악해서

4. 이미지를 저장할 경로와 파일명을 결정한 후

5. 그림추출(경로명) 메서드로 이미지를 저장

댓글