안녕하세요, 파이토치 한국사용자모임 여러분! ![]()
오늘은 딥러닝 프로젝트를 진행하면서 한 번쯤 겪어봤을 "PDF 문서 처리" 문제를 해결해줄 라이브러리를 소개합니다.
논문 데이터셋 구축, 학습 데이터 추출, 문서 기반 RAG 시스템 구현... 다들 한 번쯤 PDF에서 텍스트나 테이블을 뽑아야 했던 경험 있으시죠? ![]()
왜 PyTorch 개발자에게 PyMuPDF가 필요할까?
최근 LLM과 RAG(Retrieval-Augmented Generation) 열풍으로 문서 처리 파이프라인의 중요성이 급격히 높아졌습니다. 특히:
논문 데이터셋 구축: arXiv PDF에서 텍스트 추출하여 학습 데이터로 활용
RAG 시스템: PDF 문서를 벡터 DB에 넣기 위한 전처리
테이블 데이터 추출: 재무제표, 연구 데이터를 DataFrame으로 변환
멀티모달 학습: PDF를 이미지로 변환하여 Vision Transformer 학습
PyMuPDF는 이 모든 작업을 빠르고 정확하게 처리할 수 있는 강력한 도구입니다.
실전 활용 사례 10가지
1.
PDF 텍스트 추출 - RAG 파이프라인의 시작
LangChain이나 LlamaIndex로 RAG 시스템을 구축할 때 가장 먼저 해야 할 일이죠.
import pymupdf
doc = pymupdf.open("arxiv_paper.pdf")
full_text = ""
for page in doc:
full_text += page.get_text()
# 이제 이 텍스트를 chunking하고 embedding하면 됩니다!
Tip: get_text("blocks")를 사용하면 텍스트 블록별로 좌표 정보도 함께 얻을 수 있어, 레이아웃 기반 처리에 유용합니다.
2.
폼 자동 입력 및 플래트닝
대규모 문서 처리 자동화에 필수적인 기능입니다.
import pymupdf
doc = pymupdf.open("form.pdf")
for field in doc.widgets():
if field.field_name == "Name":
field.field_value = "Alice"
field.update()
doc.save("filled_flattened.pdf", deflate=True)
3.
테이블 추출 - 논문/재무제표 데이터 파싱
연구 논문의 실험 결과 테이블이나 재무제표를 DataFrame으로 변환할 때 핵심입니다.
import pymupdf
doc = pymupdf.open("research_paper.pdf")
page = doc[0]
blocks = page.get_text("dict")["blocks"]
# bounding box 정보를 활용해 테이블 구조 추론
for b in blocks:
print(b.get("lines"))
Tip: 복잡한 테이블은 pymupdf4llm과 함께 사용하면 Markdown 형식으로 깔끔하게 추출됩니다!
4.
워터마크 추가/제거
학습 데이터 전처리 시 워터마크 제거가 필요하거나, 생성한 문서에 브랜딩을 추가할 때 사용합니다.
import pymupdf
doc = pymupdf.open("input.pdf")
for page in doc:
page.insert_text((72, 72), "CONFIDENTIAL", fontsize=40, rotate=45, opacity=0.3)
doc.save("watermarked.pdf")
5.
주석 및 하이라이트 - 논문 리뷰 자동화
논문 리뷰 시스템이나 키워드 하이라이팅 도구 개발에 활용됩니다.
import pymupdf
doc = pymupdf.open("paper.pdf")
page = doc[0]
# "attention"이라는 단어를 모두 하이라이트
text_instances = page.search_for("attention")
for inst in text_instances:
page.add_highlight_annot(inst)
doc.save("highlighted.pdf")
6.
PDF 페이지 분할
대용량 PDF를 챕터별로 나누거나, 배치 처리를 위해 분할할 때 사용합니다.
import pymupdf
doc = pymupdf.open("textbook.pdf")
for i in range(len(doc)):
new_doc = pymupdf.open()
new_doc.insert_pdf(doc, from_page=i, to_page=i)
new_doc.save(f"chapter_{i+1}.pdf")
7.
여러 PDF 병합
여러 논문을 하나의 리뷰 문서로 합치거나, 분산된 데이터를 통합할 때 필요합니다.
import pymupdf
merged = pymupdf.open()
for fname in ["paper1.pdf", "paper2.pdf", "paper3.pdf"]:
merged.insert_pdf(pymupdf.open(fname))
merged.save("literature_review.pdf")
8.
PDF → 이미지 변환 - Vision 모델 학습 데이터 생성
Document AI, LayoutLM, Donut 같은 모델 학습 시 필수적인 전처리입니다!
import pymupdf
doc = pymupdf.open("document.pdf")
for page_number, page in enumerate(doc):
pix = page.get_pixmap(dpi=300) # 고해상도로 추출
pix.save(f"page_{page_number+1}.png")
# 이제 이 이미지들을 PyTorch Dataset으로 로드하면 됩니다!
Tip: dpi 파라미터로 해상도 조절 가능. OCR 전처리에는 300 DPI 이상 권장!
9.
텍스트 검색 및 교체 - 데이터 익명화
개인정보가 포함된 문서를 학습 데이터로 사용할 때 **익명화(redaction)**는 필수입니다.
import pymupdf
doc = pymupdf.open("document.pdf")
for page in doc:
# 이메일 주소 찾아서 마스킹
areas = page.search_for("@company.com")
for area in areas:
page.add_redact_annot(area, fill=(1, 1, 1))
page.apply_redactions()
doc.save("anonymized.pdf")
10.
PDF 압축
대용량 PDF 데이터셋을 효율적으로 저장하고 전송할 때 유용합니다.
import pymupdf
doc = pymupdf.open("large_paper.pdf")
doc.save("compressed.pdf", deflate=True, garbage=4)
PyTorch 프로젝트에 바로 적용하기
RAG 시스템 구축 예시
Copyimport pymupdf
from langchain.text_splitter import RecursiveCharacterTextSplitter
import torch
# 1. PDF 텍스트 추출
doc = pymupdf.open("knowledge_base.pdf")
text = "".join([page.get_text() for page in doc])
# 2. 텍스트 청킹
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = splitter.split_text(text)
# 3. 이제 chunks를 embedding하고 벡터 DB에 저장!
# (여기서 PyTorch 기반 embedding 모델 사용)
Document AI 데이터셋 생성 예시
import pymupdf
from torch.utils.data import Dataset
from PIL import Image
import io
class PDFImageDataset(Dataset):
def __init__(self, pdf_paths):
self.images = []
for pdf_path in pdf_paths:
doc = pymupdf.open(pdf_path)
for page in doc:
pix = page.get_pixmap(dpi=150)
img = Image.open(io.BytesIO(pix.tobytes()))
self.images.append(img)
def __len__(self):
return len(self.images)
def __getitem__(self, idx):
return self.images[idx]