notion to pptx 변환 5분컷

하는·2일 전
1

나는 노션에 익숙한데, 자료정리를 무조건 pptx로 저장하라는 회사 이해x임. 여러번 노션이나 pdf를 권유했지만 팀장님의 마음을 돌릴 순 없었다 ㅠ gpt로 계속 만져보다가 실패를 거듭한 후 찾은 최선의 방법을 공유한다.

  1. 변환하고 싶은 노션 페이지를 html로 내보내기한다.
  2. 파이썬으로 txt 변환한다.
# 입력 HTML 파일 경로
title = 'cuda upgrade'

from bs4 import BeautifulSoup
from bs4.element import NavigableString

def parse_html_to_text(node, depth=0, ol_counters=None, current_heading_level=0):
    if ol_counters is None:
        ol_counters = {}
    result = ''

    # 현재 노드가 h1, h2, h3인지 확인하여 들여쓰기 수준 결정
    if node.name in ['h1', 'h2', 'h3']:
        indent_level = 0  # 헤딩은 들여쓰기 없음
    else:
        indent_level = current_heading_level + 1  # 추가 들여쓰기 적용

    indent = '\t' * indent_level

    # 헤딩 처리
    if node.name in ['h1', 'h2', 'h3']:
        # 헤딩 텍스트 출력
        text = node.get_text(strip=True)
        if text:
            result += f"{text}\n"  # 헤딩은 들여쓰기 없음
        # 현재 헤딩 레벨 갱신
        current_heading_level = int(node.name[1])
    # 문단 처리
    elif node.name == 'p':
        text = node.get_text(strip=True)
        if text:
            result += f"{indent}{text}\n"
    # 순서 있는 목록 처리
    elif node.name == 'ol':
        # 현재 깊이의 번호를 초기화하거나 start 속성 사용
        start = node.get('start')
        if start:
            counter = int(start)
        else:
            counter = 1
        ol_counters[depth] = counter

        for li in node.find_all('li', recursive=False):
            result += parse_html_to_text(li, depth, ol_counters, current_heading_level)
        # 목록 종료 시 카운터 삭제
        del ol_counters[depth]
    # 순서 없는 목록 처리
    elif node.name == 'ul':
        for li in node.find_all('li', recursive=False):
            result += parse_html_to_text(li, depth, ol_counters, current_heading_level)
    # 목록 아이템 처리
    elif node.name == 'li':
        # 목록 아이템의 들여쓰기는 헤딩 레벨과 깊이에 따라 결정
        item_indent_level = indent_level + depth
        item_indent = '\t' * item_indent_level

        if node.parent.name == 'ol':
            number = ol_counters.get(depth, 1)
            ol_counters[depth] = number + 1
            bullet = f"{number}. "
        else:
            bullet = "- "

        # 아이템의 텍스트 내용 추출
        item_text = ''
        for child in node.contents:
            if isinstance(child, NavigableString):
                item_text += child.strip()
            elif child.name not in ['ol', 'ul']:
                item_text += child.get_text(strip=True)

        result += f"{item_indent}{bullet}{item_text}\n"

        # 자식 요소 재귀 처리
        for child in node.contents:
            if child.name in ['ul', 'ol']:
                result += parse_html_to_text(child, depth + 1, ol_counters, current_heading_level)
    # 코드 블록 처리
    elif node.name == 'pre':
        code_text = node.get_text()
        lines = code_text.split('\n')
        for line in lines:
            if line.strip():  # 빈 줄은 무시
                result += f"{indent}{line}\n"
            else:
                result += "\n"
    # 불필요한 요소 필터링
    elif node.name in ['figure', 'img', 'style', 'script']:
        pass  # 해당 요소는 무시
    # 텍스트 노드 처리
    elif isinstance(node, NavigableString):
        text = node.strip()
        if text:
            result += f"{indent}{text}\n"
    # 기타 요소 처리
    else:
        for child in node.children:
            result += parse_html_to_text(child, depth, ol_counters, current_heading_level)

    return result

# 입력 HTML 파일 경로
input_file = title + '.html'

# 출력 텍스트 파일 경로
output_file = title + '.txt'

# HTML 파일 읽기
with open(input_file, 'r', encoding='utf-8') as f:
    html_content = f.read()

# BeautifulSoup으로 파싱
soup = BeautifulSoup(html_content, 'html.parser')

# body 태그 선택
body = soup.find('body')

# 텍스트 변환 실행
text_output = parse_html_to_text(body)

# 결과를 텍스트 파일로 저장
with open(output_file, 'w', encoding='utf-8') as f:
    f.write(text_output)

print(f"변환이 완료되었습니다. 결과는 '{output_file}'에 저장되었습니다.")
  1. python으로 txt를 pptx로 변환한다.
from pptx import Presentation
from pptx.util import Inches, Pt
import re

# 입력 텍스트 파일 경로
input_txt_file = output_file

# 출력 PPTX 파일 경로
output_pptx_file = title + '.pptx'

# 프레젠테이션 객체 생성
prs = Presentation()

# 슬라이드 크기를 와이드스크린(16:9)으로 설정
prs.slide_width = Inches(13.33)
prs.slide_height = Inches(7.5)

# 텍스트 파일 읽기
with open(input_txt_file, 'r', encoding='utf-8') as f:
    lines = f.readlines()

# 1. 첫 장에 제목 슬라이드 추가 (slide_layouts[0] 사용)
title_slide_layout = prs.slide_layouts[0]  # 제목 슬라이드 레이아웃
title_slide = prs.slides.add_slide(title_slide_layout)

# 첫 번째 줄을 제목으로 사용
first_line = lines[0].strip()  # 첫 번째 줄에서 개행 문자 제거

# 제목과 부제목 설정
title = title_slide.shapes.title
title.text = first_line  # 첫 번째 줄을 제목으로 설정

# 이후 슬라이드 레이아웃 선택 (제목 및 내용)
slide_layout = prs.slide_layouts[1]

current_slide = None
bullet_levels = []

for i, line in enumerate(lines):  
    stripped_line = line.strip('\n')
    # 들여쓰기 수준 계산
    indent_level = len(re.match(r'^(\t*)', stripped_line).group(1))
    content = stripped_line.lstrip('\t')

    if i == 0:
        # 첫 번째 슬라이드는 이미 제목으로 사용했으므로 건너뜀
        continue

    # 헤딩인지 확인 (h1, h2, h3는 들여쓰기 없음)
    if indent_level == 0:
        # 새로운 슬라이드 생성
        current_slide = prs.slides.add_slide(slide_layout)
        title_placeholder = current_slide.shapes.title
        body_placeholder = current_slide.placeholders[1]
        tf = body_placeholder.text_frame
        tf.clear()

        # 두 번째 슬라이드의 제목도 첫 번째 줄을 사용
        title_placeholder.text = first_line if i == 1 else content
        bullet_levels = []
    else:
        if current_slide is None:
            # 슬라이드가 없으면 새로 생성
            current_slide = prs.slides.add_slide(slide_layout)
            body_placeholder = current_slide.placeholders[1]
            tf = body_placeholder.text_frame
            tf.clear()
        else:
            body_placeholder = current_slide.placeholders[1]
            tf = body_placeholder.text_frame

        # 리스트 아이템인지 확인
        bullet_match = re.match(r'^(- |\d+\. )(.*)', content)
        if bullet_match:
            bullet_text = bullet_match.group(2)
            p = tf.add_paragraph()
            p.text = bullet_text
            p.level = indent_level - 1  # 들여쓰기 수준에 따라 bullet level 설정
        else:
            # 일반 텍스트
            p = tf.add_paragraph()
            p.text = content
            p.level = indent_level - 1  # 들여쓰기 수준에 따라 bullet level 설정

# 프레젠테이션 저장
prs.save(output_pptx_file)

print(f"텍스트 파일이 '{output_pptx_file}'로 변환되었습니다.")
  1. power point에서 pptx 열고 회사 템플릿을 불러온다.

코드 더 수정해야지... 아직 태그에 종속적인 코드다.

개선점

  1. 코드 부분이 삭제됨
  2. 이미지 넣기 안됨
  3. 프로그램 (exe) 형식으로 만들기
profile
천천히 꾸준히 취미처럼 냐미😋

0개의 댓글