Python으로 DOCX 파일의 이미지 추출 자동화

발행: (2025년 12월 23일 오전 11:54 GMT+9)
12 min read
원문: Dev.to

Source: Dev.to

위에 제공된 소스 링크 외에 번역할 텍스트가 포함되어 있지 않습니다. 번역을 원하는 본문 내용을 알려주시면 한국어로 번역해 드리겠습니다.

Source:

Python으로 Word 문서에서 이미지 추출하기

Word 문서를 다룰 때는 텍스트뿐만 아니라 이미지도 중요한 요소입니다. 많은 보고서, 프레젠테이션, 창작물에 이미지가 포함되어 있기 때문에, 이러한 삽입된 이미지를 수동으로 추출하는 작업은 특히 문서가 많을 경우 매우 번거롭고 시간도 많이 소요되며 오류가 발생하기 쉽습니다. 수십(혹은 수백) 개의 Word 파일을 열어 각각의 이미지를 오른쪽 클릭하고 개별적으로 저장한다는 상황을 상상해 보세요. 이는 비효율적일 뿐만 아니라 데이터 처리와 콘텐츠 관리에 큰 장애물이 됩니다.

다행히 Python을 사용하면 우아한 해결책을 구현할 수 있습니다. 특화된 라이브러리를 활용하면 이미지 추출 전체 과정을 자동화하여 수동 작업을 빠르고 스크립트 기반의 작업으로 전환할 수 있습니다. 이 튜토리얼에서는 Word 문서에서 이미지를 대량으로 추출하는 견고한 Python 스크립트를 만드는 방법을 단계별로 안내하여 생산성을 높이고 정확성을 보장합니다.

라이브러리가 필요한 이유

Word 문서(특히 최신 .docx 형식)는 단순 텍스트 파일이 아닙니다. 여러 XML 파일, 미디어 파일 및 기타 리소스를 포함한 ZIP 압축 파일이며, 이들 요소가 문서의 구조, 내용, 스타일을 정의합니다. 텍스트만 직접 파싱하는 방식으로는 이미지와 같은 삽입 객체를 추출할 수 없습니다. 이러한 복잡한 구조를 이해하고 탐색하려면 전용 라이브러리가 필요합니다.

Spire.Doc for Python 소개

우리는 Spire.Doc for Python을 사용할 것입니다. 이 라이브러리는 Python 애플리케이션 내에서 Word 문서를 생성, 읽기, 편집 및 변환하도록 설계되었습니다. 풍부한 API를 통해 개발자는 문단, 표, 도형은 물론 핵심적인 삽입 이미지까지 다양한 문서 요소에 접근하고 조작할 수 있어 이미지 추출 작업이 매우 간단해집니다.

1. 라이브러리 설치

pip install spire.doc

2. 프로젝트 구조 설정

스크립트와 같은 디렉터리에 두 개의 폴더를 만드세요:

  • InputDocuments – 여기에서 처리하려는 Word 파일을 넣습니다.
  • ExtractedImages – 추출된 이미지가 이 폴더에 저장됩니다.

3. 모듈 가져오기 및 디렉터리 정의

import os
import queue  # For traversing document elements
from spire.doc import *
from spire.doc.common import *

# Define input and output directories
INPUT_DIR = "InputDocuments"      # Folder containing your Word documents
OUTPUT_DIR = "ExtractedImages"    # Folder to save extracted images

# Create output directory if it doesn't exist
if not os.path.exists(OUTPUT_DIR):
    os.makedirs(OUTPUT_DIR)

print(f"Input directory: {os.path.abspath(INPUT_DIR)}")
print(f"Output directory: {os.path.abspath(OUTPUT_DIR)}")

4. 핵심 추출 로직

def extract_images_from_doc(doc_path, output_folder):
    """
    Extracts images from a single Word document and saves them to a specified folder.
    """
    document = Document()
    try:
        document.LoadFromFile(doc_path)
    except Exception as e:
        print(f"Error loading document {doc_path}: {e}")
        return

    extracted_images_count = 0
    nodes = queue.Queue()
    nodes.put(document)

    while not nodes.empty():
        node = nodes.get()
        # Iterate through all child objects of the current node
        for i in range(node.ChildObjects.Count):
            child = node.ChildObjects.get_Item(i)

            # -------------------------------------------------
            # Image extraction
            # -------------------------------------------------
            if child.DocumentObjectType == DocumentObjectType.Picture:
                picture = child if isinstance(child, DocPicture) else None
                if picture is not None:
                    image_bytes = picture.ImageBytes

                    # Construct a unique filename (default to PNG)
                    image_filename = f"image_{extracted_images_count + 1}.png"
                    image_filepath = os.path.join(output_folder, image_filename)

                    try:
                        with open(image_filepath, "wb") as img_file:
                            img_file.write(image_bytes)
                        extracted_images_count += 1
                        print(f"  Extracted: {image_filepath}")
                    except Exception as e:
                        print(f"    Error saving image to {image_filepath}: {e}")

            # -------------------------------------------------
            # Continue traversal for composite objects
            # -------------------------------------------------
            elif isinstance(child, ICompositeObject):
                nodes.put(child)

    document.Close()
    print(f"Finished processing '{os.path.basename(doc_path)}' – "
          f"{extracted_images_count} image(s) extracted.")

5. 여러 문서 일괄 처리

def batch_extract_images(input_dir, output_dir):
    """
    Processes all .docx files in the input directory,
    extracting images from each into the output directory.
    """
    for filename in os.listdir(input_dir):
        if filename.lower().endswith(('.docx', '.doc')):
            doc_path = os.path.join(input_dir, filename)
            # Create a subfolder for each document's images (optional)
            doc_output_folder = os.path.join(output_dir, os.path.splitext(filename)[0])
            if not os.path.exists(doc_output_folder):
                os.makedirs(doc_output_folder)

            print(f"\nProcessing: {doc_path}")
            extract_images_from_doc(doc_path, doc_output_folder)

if __name__ == "__main__":
    batch_extract_images(INPUT_DIR, OUTPUT_DIR)

스크립트를 실행하면:

  1. InputDocuments 폴더에서 .docx/.doc 파일을 스캔합니다.
  2. ExtractedImages 안에 각 문서마다 전용 하위 폴더를 생성합니다.
  3. 모든 포함된 이미지를 추출하여 순차적인 이름(image_1.png, image_2.png, …)으로 저장합니다.

6. 요약

  • Problem: 많은 Word 파일에서 수동으로 이미지를 추출하는 것은 비효율적입니다.
  • Solution: Spire.Doc for Python을 사용하여 문서 구조를 프로그래밍 방식으로 탐색하고 삽입된 이미지를 저장합니다.
  • Result: 이미지를 대량으로 추출하는 재사용 가능한 스크립트로, 시간 절약과 오류 감소를 실현합니다.

스크립트를 자유롭게 수정하세요 (예: 명명 규칙 변경, 추가 포맷 지원, 다른 워크플로와 통합 등). 즐거운 코딩 되세요!

Source:

Spire.Doc for Python을 사용한 Word 문서에서 이미지 추출하기

아래는 바로 실행할 수 있는 전체 스크립트이며, 다음을 수행합니다:

  1. 폴더를 스캔하여 모든 .docx 파일을 찾습니다.
  2. 각 문서마다 ExtractedImages 디렉터리 안에 전용 하위 폴더를 생성합니다.
  3. 임베드된 모든 그림(표, 텍스트 상자 등 내부에 포함된 것 포함)을 추출하여 해당 폴더에 저장합니다.

1. Imports & Global Paths

import os
import sys
from spire.doc import Document, DocumentObjectType
# ── USER‑CONFIGURABLE PATHS ────────────────────────────────────────
INPUT_DIR  = "WordDocs"          # .docx 파일이 들어 있는 폴더
OUTPUT_DIR = "ExtractedImages"   # 추출된 이미지가 저장될 위치
# ───────────────────────────────────────────────────────────────────────

2. Helper: Extract Images from a Single Document

def extract_images_from_doc(doc_path: str, output_folder: str) -> int:
    """
    Extracts all images from a single Word document and saves them to
    `output_folder`. Returns the number of images extracted.
    """
    try:
        document = Document()
        document.LoadFromFile(doc_path)
    except Exception as e:
        print(f"[ERROR] Could not load '{doc_path}': {e}")
        return 0

    # Ensure the output folder exists
    os.makedirs(output_folder, exist_ok=True)

    extracted_images_count = 0
    queue = list(document.Sections[0].Body.ChildObjects)   # start traversal

    while queue:
        child = queue.pop(0)

        # Enqueue nested children (e.g., table cells, text boxes)
        if hasattr(child, "ChildObjects") and child.ChildObjects:
            queue.extend(child.ChildObjects)

        # Identify picture objects
        if child.DocumentObjectType == DocumentObjectType.Picture:
            picture = child
            img_bytes = picture.ImageBytes

            # Determine a file extension – default to .png if unknown
            ext = ".png"
            if hasattr(picture, "ImageType"):
                ext = f".{picture.ImageType.name.lower()}"

            img_name = f"image_{extracted_images_count + 1}{ext}"
            img_path = os.path.join(output_folder, img_name)

            try:
                with open(img_path, "wb") as f:
                    f.write(img_bytes)
                extracted_images_count += 1
                print(f"  → Saved: {img_name}")
            except Exception as e:
                print(f"[ERROR] Could not save image '{img_name}': {e}")

    document.Close()
    print(f". Extracted {extracted_images_count} images.")
    return extracted_images_count

작동 방식

단계설명
문서 로드document.LoadFromFile(doc_path) 로 Word 파일을 읽어들입니다.
큐 기반 순회테이블, 텍스트 상자 등 중첩 구조를 모두 방문하도록 보장합니다.
이미지 식별child.DocumentObjectType == DocumentObjectType.Picture 로 그림 객체를 판별합니다.
바이트 가져오기picture.ImageBytes 로 원시 이미지 데이터를 얻습니다.
디스크에 저장바이트를 파일에 쓰며, picture.ImageType 이 제공되면 그에 맞는 확장자를 사용하고, 없으면 기본 .png 로 저장합니다.
오류 처리try/except 블록으로 로드 또는 저장 실패 시 오류를 잡아 보고합니다.

3. Bulk Processing: All .docx Files in a Folder

def bulk_extract_images(input_dir: str, output_dir: str) -> None:
    """
    Walks through `input_dir`, extracts images from every .docx file,
    and stores them in sub‑folders under `output_dir`.
    """
    total_images_extracted = 0

    # Gather all .docx files
    doc_files = [f for f in os.listdir(input_dir) if f.lower().endswith(".docx")]

    if not doc_files:
        print(f"No .docx files found in '{input_dir}'.")
        return

    print(f"\nFound {len(doc_files)} Word document(s) to process.\n")

    for doc_file in doc_files:
        full_doc_path = os.path.join(input_dir, doc_file)

        # Create a folder named after th

Source:

e document (without extension)
        doc_name = os.path.splitext(doc_file)[0]
        doc_output_folder = os.path.join(output_dir, doc_name)
        os.makedirs(doc_output_folder, exist_ok=True)

        print(f"Processing '{doc_file}' …")
        images_count = extract_images_from_doc(full_doc_path, doc_output_folder)
        total_images_extracted += images_count

    print(f"\n✅ Bulk extraction complete – total images extracted: {total_images_extracted}")

4. 메인 실행 블록

if __name__ == "__main__":
    # -----------------------------------------------------------------
    # Create the input folder if it does not exist (for demo purposes)
    # -----------------------------------------------------------------
    if not os.path.isdir(INPUT_DIR):
        os.makedirs(INPUT_DIR, exist_ok=True)
        print(f"Created '{INPUT_DIR}'. Please add .docx files here before re‑running.")
        sys.exit(0)

    # Run the bulk extractor
    bulk_extract_images(INPUT_DIR, OUTPUT_DIR)

5. 빠른 참고: 사용된 Spire.Doc for Python API

메서드 / 속성설명
Document()새 Word 문서 객체를 생성합니다.
document.LoadFromFile(path)디스크에서 Word 파일을 로드합니다.
document.Sections[0].Body.ChildObjects최상위 자식 객체(단락, 표, 그림 등)를 반환합니다.
DocumentObjectType.Picture그림 객체를 식별하는 열거형 값입니다.
picture.ImageBytes삽입된 이미지의 원시 바이트 배열입니다.
document.Close()문서가 보유한 리소스를 해제합니다.

다음 단계 및 향상

  • 세밀한 오류 처리 – 특정 예외(FileNotFoundError, IOError 등)를 잡아 파일에 기록합니다.
  • 맞춤형 파일명 규칙 – 원본 문서 이름, 타임스탬프 또는 해시를 이미지 파일명에 포함시켜 추적성을 높입니다.
  • 포맷 변환Pillow(pip install pillow)를 사용해 추출된 모든 이미지를 동일한 포맷(예: JPEG)으로 변환합니다.
  • 병렬 처리 – 수천 개의 문서에 대해 extract_images_from_docmultiprocessing.Pool로 감싸 실행 속도를 높입니다.

요약

위 스크립트는 Word 파일에서 모든 이미지를 추출하는 번거로운 작업을 자동화합니다. .docx 파일을 WordDocs 폴더에 넣고 스크립트를 실행하기만 하면 다음과 같은 깔끔한 디렉터리 구조가 생성됩니다:

ExtractedImages/
├─ Report_Q1/
│  ├─ image_1.png
│  └─ image_2.jpg
├─ Invoice_2024/
│  ├─ image_1.png
│  └─ image_2.png
└─ …

코드를 워크플로에 맞게 자유롭게 수정하고, 로깅을 추가하거나 추가적인 Spire.Doc 기능을 확장해 보세요. 자동화 즐기세요!

Back to Blog

관련 글

더 보기 »