파이썬에서 PDFMiner를 사용하여 PDF에서 텍스트 추출하기

파이썬으로 PDF 텍스트 추출을 완벽하게 마스터하세요.

Page content

PDFMiner.six은 PDF 문서에서 텍스트, 메타데이터 및 레이아웃 정보를 추출하기 위한 강력한 Python 라이브러리입니다. 이 가이드는 우리의 2026년 문서 작업 툴: 마크다운, 라텍스, PDF 및 인쇄 워크플로우 허브의 일부입니다.

간단한 PDF 리더와 달리, PDF 구조에 대한 깊은 분석을 제공하고 복잡한 레이아웃을 효과적으로 처리합니다.

PDF에서 마크다운으로 텍스트 추출 - IPAD 시각화

PDFMiner란 무엇이며 왜 사용해야 하나요?

PDFMiner는 PDF 문서에서 텍스트를 추출하고 분석하기 위해 설계된 순수 Python 라이브러리입니다. .six 버전은 Python 3.x를 지원하는 활발히 유지보수되는 포크이며, 원래의 PDFMiner 프로젝트는 더 이상 업데이트되지 않습니다.

주요 기능:

  • 외부 의존성이 없는 순수 Python 구현
  • 상세한 레이아웃 분석 및 텍스트 위치 정보
  • 글꼴 및 문자 인코딩 감지
  • 암호화된 PDF 지원
  • 명령줄 도구 포함
  • 커스텀 처리를 위한 확장 가능한 아키텍처

PDFMiner는 텍스트 추출에 대한 정확한 제어가 필요하거나 레이아웃 정보를 유지해야 하거나 복잡한 다중 열 문서를 다루는 경우 특히 유용합니다. 다른 대안보다 느릴 수 있지만, 정확성과 상세한 분석 능력으로 인해 문서 처리 파이프라인에서 선호되는 선택입니다. 반대 방향의 워크플로우에서는 파이썬에서 PDF를 생성하는 방법에 관심이 있을 수 있습니다.

설치 및 설정

pip을 사용하여 PDFMiner.six를 설치합니다:

pip install pdfminer.six

가상 환경(추천):

python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate
pip install pdfminer.six

Python 패키지 관리에 익숙하지 않다면, pip 및 가상 환경에 대한 더 많은 정보를 위해 Python 체크리스트를 확인하세요.

설치 확인:

pdf2txt.py --version

라이브러리는 여러 명령줄 도구를 포함합니다:

  • pdf2txt.py - PDF에서 텍스트 추출
  • dumppdf.py - PDF 내부 구조 덤프
  • latin2ascii.py - 라틴 문자를 ASCII로 변환

이 도구들은 PDF 조작 유틸리티인 Poppler와 같은 추가 기능(예: 페이지 추출 및 형식 변환)을 제공하는 다른 도구들과 보완합니다.

기본 텍스트 추출

간단한 텍스트 추출

PDF에서 텍스트를 추출하는 가장 간단한 방법:

from pdfminer.high_level import extract_text

# PDF에서 모든 텍스트 추출
text = extract_text('document.pdf')
print(text)

이 고급 API는 대부분의 일반적인 사용 사례를 처리하며, 전체 문서를 단일 문자열로 반환합니다.

특정 페이지에서 텍스트 추출

특정 페이지에서 텍스트를 추출하려면:

from pdfminer.high_level import extract_text

# 페이지 2-5에서 텍스트 추출 (0 기준)
text = extract_text('document.pdf', page_numbers=[1, 2, 3, 4])
print(text)

이 방법은 대규모 문서에서 특정 섹션만 필요할 경우 성능을 크게 향상시켜 줍니다.

페이지별 텍스트 추출

페이지별로 처리하려면:

from pdfminer.high_level import extract_pages
from pdfminer.layout import LTTextContainer

for page_layout in extract_pages('document.pdf'):
    for element in page_layout:
        if isinstance(element, LTTextContainer):
            print(element.get_text())

이 접근법은 페이지 구조가 달라지는 문서를 처리할 때 각 페이지의 처리 방식에 대한 더 많은 제어를 제공합니다.

고급 레이아웃 분석

LAParams 이해

LAParams(레이아웃 분석 파라미터)는 PDFMiner가 문서 레이아웃을 해석하는 방법을 제어합니다. PDFMiner와 더 간단한 라이브러리 사이의 차이를 이해하는 것이 여기서 중요합니다 - PDFMiner는 실제로 텍스트 요소 간의 공간적 관계를 분석합니다.

from pdfminer.high_level import extract_text
from pdfminer.layout import LAParams

# 사용자 정의 LAParams 생성
laparams = LAParams(
    line_overlap=0.5,      # 라인 겹침 최소치
    char_margin=2.0,       # 문자 간격
    line_margin=0.5,       # 라인 간격
    word_margin=0.1,       # 단어 간격
    boxes_flow=0.5,        # 텍스트 박스 흐름 임계값
    detect_vertical=True,  # 수직 텍스트 감지
    all_texts=False        # 박스 내 텍스트만 추출
)

text = extract_text('document.pdf', laparams=laparams)

파라미터 설명:

  • line_overlap: 수직으로 겹쳐야 하는 라인의 최소 겹침 (0.0-1.0)
  • char_margin: 동일한 단어 내에서 문자 간격 (문자 너비의 배수)
  • line_margin: 동일한 단락 내에서 라인 간격
  • word_margin: 단어 분리 임계값
  • boxes_flow: 텍스트 박스 흐름 방향 임계값
  • detect_vertical: 수직 텍스트 감지 (아시아 언어에서 흔함)
  • all_texts: 박스 내 텍스트만 추출

레이아웃 정보 추출

상세한 위치 및 글꼴 정보를 얻는 방법:

from pdfminer.high_level import extract_pages
from pdfminer.layout import LTTextBox, LTTextLine, LTChar

for page_layout in extract_pages('document.pdf'):
    for element in page_layout:
        if isinstance(element, LTTextBox):
            # 경계 상자 좌표 얻기
            x0, y0, x1, y1 = element.bbox
            print(f"({x0}, {y0})에 있는 텍스트: {element.get_text()}")
            
            # 라인 반복
            for text_line in element:
                if isinstance(text_line, LTTextLine):
                    # 문자 레벨 세부 정보
                    for char in text_line:
                        if isinstance(char, LTChar):
                            print(f"문자: {char.get_text()}, "
                                  f"글꼴: {char.fontname}, "
                                  f"크기: {char.height}")

이 수준의 세부 정보는 문서 분석, 폼 추출 또는 문서 구조를 프로그래밍적으로 이해할 때 매우 유용합니다.

다양한 PDF 유형 처리

암호화된 PDF

PDFMiner는 암호가 있는 PDF를 처리할 수 있습니다:

from pdfminer.high_level import extract_text

# 암호가 있는 PDF에서 텍스트 추출
text = extract_text('encrypted.pdf', password='your_password')

PDFMiner는 PDF 수준에서 텍스트 추출을 방지하는 보안 제한을 우회할 수 없습니다.

다중 열 문서

다중 열 문서의 경우 LAParams를 조정하세요:

from pdfminer.high_level import extract_text
from pdfminer.layout import LAParams

# 다중 열 레이아웃 최적화
laparams = LAParams(
    detect_vertical=False,
    line_margin=0.3,
    word_margin=0.1,
    boxes_flow=0.3  # 더 나은 열 감지 위해 낮은 값
)

text = extract_text('multi_column.pdf', laparams=laparams)

boxes_flow 파라미터는 다중 열 문서에 특히 중요합니다 - 낮은 값은 PDFMiner가 별도의 열을 구분하는 데 도움이 됩니다.

비영어 및 유니코드 텍스트

PDFMiner는 유니코드를 잘 처리하지만, 올바른 인코딩을 보장하세요:

from pdfminer.high_level import extract_text

# 유니코드 지원으로 텍스트 추출
text = extract_text('multilingual.pdf', codec='utf-8')

# UTF-8 인코딩으로 파일에 저장
with open('output.txt', 'w', encoding='utf-8') as f:
    f.write(text)

스캔된 PDF 작업

PDFMiner는 스캔된 PDF(이미지)에서 텍스트를 직접 추출할 수 없습니다. 이는 OCR(광학 문자 인식)이 필요합니다. 그러나 PDFMiner를 OCR 도구와 통합할 수 있습니다.

PDF가 스캔되어 있는지 확인하는 방법:

from pdfminer.high_level import extract_text
from pdfminer.high_level import extract_pages
from pdfminer.layout import LTFigure, LTImage

def is_scanned_pdf(pdf_path):
    """PDF가 스캔되어 있는지 확인 (대부분 이미지인 경우)"""
    text_count = 0
    image_count = 0
    
    for page_layout in extract_pages(pdf_path):
        for element in page_layout:
            if isinstance(element, (LTFigure, LTImage)):
                image_count += 1
            elif hasattr(element, 'get_text'):
                if element.get_text().strip():
                    text_count += 1
    
    # 이미지가 많고 텍스트가 적으면 스캔된 것으로 간주
    return image_count > text_count * 2

if is_scanned_pdf('document.pdf'):
    print("이 PDF는 스캔된 것으로 보입니다 - OCR 사용")
else:
    text = extract_text('document.pdf')
    print(text)

스캔된 PDF의 경우 Tesseract OCR과 통합하거나 먼저 PDF에서 이미지 추출 도구를 사용하여 이미지를 추출한 후 OCR을 적용하는 것이 좋습니다.

명령줄 사용법

PDFMiner는 강력한 명령줄 도구를 포함합니다:

명령줄 도구로 텍스트 추출

# 표준출력으로 텍스트 추출
pdf2txt.py document.pdf

# 파일로 저장
pdf2txt.py -o output.txt document.pdf

# 특정 페이지 추출
pdf2txt.py -p 1,2,3 document.pdf

# HTML로 추출
pdf2txt.py -t html -o output.html document.pdf

고급 옵션

# 커스텀 레이아웃 파라미터
pdf2txt.py -L 0.3 -W 0.1 document.pdf

# 상세한 레이아웃으로 추출 (XML)
pdf2txt.py -t xml -o layout.xml document.pdf

# 암호 설정
pdf2txt.py -P mypassword encrypted.pdf

이 명령줄 도구는 빠른 테스트, 쉘 스크립트 및 자동화 워크플로우 통합에 훌륭합니다.

성능 최적화

대규모 PDF 처리

대규모 문서의 경우 다음 최적화 전략을 고려하세요:

from pdfminer.high_level import extract_pages
from pdfminer.layout import LAParams

# 필요한 페이지만 처리
def extract_page_range(pdf_path, start_page, end_page):
    text_content = []
    for i, page_layout in enumerate(extract_pages(pdf_path)):
        if i < start_page:
            continue
        if i >= end_page:
            break
        text_content.append(page_layout)
    return text_content

# 속도를 위해 레이아웃 분석 비활성화
from pdfminer.high_level import extract_text
text = extract_text('large.pdf', laparams=None)  # 훨씬 빠름

배치 처리

여러 PDF를 효율적으로 처리하려면:

from multiprocessing import Pool
from pdfminer.high_level import extract_text
import os

def process_pdf(pdf_path):
    """단일 PDF 파일 처리"""
    try:
        text = extract_text(pdf_path)
        output_path = pdf_path.replace('.pdf', '.txt')
        with open(output_path, 'w', encoding='utf-8') as f:
            f.write(text)
        return f"처리됨: {pdf_path}"
    except Exception as e:
        return f"{pdf_path} 처리 오류: {str(e)}"

# 병렬 처리
def batch_process_pdfs(pdf_directory, num_workers=4):
    pdf_files = [os.path.join(pdf_directory, f) 
                 for f in os.listdir(pdf_directory) 
                 if f.endswith('.pdf')]
    
    with Pool(num_workers) as pool:
        results = pool.map(process_pdf, pdf_files)
    
    for result in results:
        print(result)

# 사용법
batch_process_pdfs('/path/to/pdfs', num_workers=4)

일반적인 문제 및 해결 방법

문제: 텍스트 순서 오류

문제: 추출된 텍스트가 뒤죽박죽이거나 순서가 잘못됨.

해결: LAParams 조정, 특히 boxes_flow:

from pdfminer.layout import LAParams
laparams = LAParams(boxes_flow=0.3)  # 다른 값 시도
text = extract_text('document.pdf', laparams=laparams)

문제: 단어 간 공백 누락

문제: 단어가 끝없이 이어짐.

해결: word_margin 증가:

laparams = LAParams(word_margin=0.2)  # 기본값 0.1에서 증가
text = extract_text('document.pdf', laparams=laparams)

문제: 인코딩 오류

문제: 이상한 문자 또는 인코딩 오류.

해결: 명시적으로 codec 지정:

text = extract_text('document.pdf', codec='utf-8')

문제: 대규모 PDF에서 메모리 오류

문제: 대규모 파일에서 메모리 부족 오류.

해결: 페이지별 처리:

def extract_text_chunked(pdf_path, chunk_size=10):
    """메모리 사용 감소를 위한 텍스트 추출"""
    all_text = []
    page_count = 0
    
    for page_layout in extract_pages(pdf_path):
        page_text = []
        for element in page_layout:
            if hasattr(element, 'get_text'):
                page_text.append(element.get_text())
        
        all_text.append(''.join(page_text))
        page_count += 1
        
        # 청크별 처리
        if page_count % chunk_size == 0:
            yield ''.join(all_text)
            all_text = []
    
    # 남은 텍스트 처리
    if all_text:
        yield ''.join(all_text)

PDFMiner 대안 비교

PDFMiner를 사용할 때와 다른 라이브러리를 사용할 때의 차이를 이해하는 것이 중요합니다:

PDFMiner vs PyPDF2

PyPDF2는 더 간단하고 빠르지만 정확도는 낮습니다:

  • PyPDF2 사용 시: 간단한 PDF, 빠른 추출, PDF 병합/분할
  • PDFMiner 사용 시: 복잡한 레이아웃, 정확한 텍스트 위치, 상세한 분석

PDFMiner vs pdfplumber

pdfplumber는 PDFMiner에 기반하여 더 높은 수준의 API를 제공합니다:

  • pdfplumber 사용 시: 테이블 추출, 간단한 API, 빠른 프로토타이핑
  • PDFMiner 사용 시: 최대 제어, 커스텀 처리, 프로덕션 시스템

PDFMiner vs PyMuPDF (fitz)

PyMuPDF는 C 의존성이 있지만 훨씬 빠릅니다:

  • PyMuPDF 사용 시: 성능이 중요한 경우, 대규모 처리
  • PDFMiner 사용 시: 순수 Python 요구, 상세한 레이아웃 분석

실용 예제: 문서 추출 및 분석

다음은 텍스트를 추출하고 문서 통계를 제공하는 완전한 예제입니다:

from pdfminer.high_level import extract_pages, extract_text
from pdfminer.layout import LTTextBox, LTChar
from collections import Counter
import re

def analyze_pdf(pdf_path):
    """텍스트 추출 및 문서 분석"""
    
    # 전체 텍스트 추출
    full_text = extract_text(pdf_path)
    
    # 통계
    stats = {
        'total_chars': len(full_text),
        'total_words': len(full_text.split()),
        'total_lines': full_text.count('\n'),
        'fonts': Counter(),
        'font_sizes': Counter(),
        'pages': 0
    }
    
    # 상세 분석
    for page_layout in extract_pages(pdf_path):
        stats['pages'] += 1
        
        for element in page_layout:
            if isinstance(element, LTTextBox):
                for line in element:
                    for char in line:
                        if isinstance(char, LTChar):
                            stats['fonts'][char.fontname] += 1
                            stats['font_sizes'][round(char.height, 1)] += 1
    
    return {
        'text': full_text,
        'stats': stats,
        'most_common_font': stats['fonts'].most_common(1)[0] if stats['fonts'] else None,
        'most_common_size': stats['font_sizes'].most_common(1)[0] if stats['font_sizes'] else None
    }

# 사용법
result = analyze_pdf('document.pdf')
print(f"페이지 수: {result['stats']['pages']}")
print(f"단어 수: {result['stats']['total_words']}")
print(f"주요 글꼴: {result['most_common_font']}")
print(f"주요 크기: {result['most_common_size']}")

문서 처리 파이프라인과의 통합

PDFMiner는 더 큰 문서 처리 워크플로우에서 잘 작동합니다. 예를 들어, RAG(검색 증강 생성) 시스템 또는 문서 관리 솔루션을 구축할 때, 다른 파이썬 도구와 결합하여 완전한 파이프라인을 만들 수 있습니다.

PDF에서 텍스트를 추출한 후, 다른 형식으로 변환해야 하는 경우가 많습니다. 파이썬 라이브러리로 HTML 콘텐츠를 마크다운으로 변환하거나, 심지어 LLM 기반 변환으로 Ollama 사용하여 지능적인 문서 변환을 수행할 수 있습니다. 이러한 기술은 PDF 추출이 HTML과 같은 구조화된 텍스트를 생성하는 경우에 특히 유용합니다.

포괄적인 문서 변환 파이프라인을 구축하려면 워드 문서를 마크다운으로 변환하는 것도 고려해야 합니다. 이를 통해 여러 문서 형식을 공통 출력 형식으로 처리하는 통합 워크플로우를 생성할 수 있습니다.

최고의 실천 방법

  1. 복잡한 문서에는 항상 LAParams 사용 - 기본 설정은 간단한 문서에 적합하지만, 복잡한 레이아웃의 경우 LAParams를 조정하면 결과가 크게 향상됩니다.

  2. 대량 처리 전에 샘플 페이지 테스트 - 대량의 배치를 처리하기 전에 대표적인 샘플 페이지에서 추출 설정을 테스트하세요.

  3. 예외 처리를 잘 처리 - PDF 파일이 손상되거나 잘못된 경우가 있을 수 있습니다. 항상 추출 코드를 try-except 블록으로 감싸세요.

  4. 추출된 텍스트 캐시 - 반복 처리 시, 추출된 텍스트를 캐시하여 재처리를 피하세요.

  5. 추출된 텍스트 검증 - 추출 품질을 확인하기 위해 검증 체크를 구현하세요(예: 최소 텍스트 길이, 예상 키워드).

  6. 특정 사용 사례에 대안 고려 - PDFMiner는 강력하지만, 특정한 경우(예: 테이블 추출에 tabula-py) 전문 도구가 더 적합할 수 있습니다.

  7. PDFMiner 업데이트 유지 - .six 포크는 활발히 유지보수되고 있습니다. 버그 수정 및 개선을 위해 항상 업데이트하세요.

  8. 코드를 적절히 문서화 - PDF 추출 스크립트를 공유할 때, 마크다운 코드 블록과 함께 구문 강조를 사용하여 가독성을 높이세요.

결론

PDFMiner.six는 Python 개발자에게 PDF 문서를 다루는 데 필수적인 도구입니다. 순수 Python 구현, 상세한 레이아웃 분석, 확장 가능한 아키텍처로 인해 프로덕션 문서 처리 시스템에 이상적입니다. 간단한 라이브러리보다 학습 곡선이 높지만, 복잡한 PDF 추출 작업에 필요한 정확성과 제어는 뛰어납니다.

문서 관리 시스템을 구축하거나 과학 논문을 분석하거나 머신러닝 파이프라인에 데이터를 추출하려면 PDFMiner는 Python에서 신뢰할 수 있는 PDF 텍스트 추출 기반을 제공합니다.

관련 자료

이 사이트의 관련 기사

외부 참조