Extract text, tables, layout, and evidence from business documents. — Claude Skill
Claude Code용 Claude 스킬 · 제공: Claude Office Skills · 실행: /doc-parser (Claude 내)·업데이트: 2026년 6월 14일·vmain@9c4c7d5
PDF, DOCX, 이미지, 스캔 문서를 구조화된 텍스트와 표로 파싱해 팀이 문서 근거를 분석, 보고, 워크플로에 사용할 수 있게 합니다.
- PDF, Word 문서, 이미지, 스캔 파일에서 텍스트와 표를 추출합니다.
- 페이지, 섹션, 표 맥락을 보존해 근거를 감사하기 쉽게 합니다.
- 복잡한 문서를 분석, 비교, 보고서에 쓸 수 있는 구조화 입력으로 바꿉니다.
- 사람 검토가 필요한 불확실한 추출 결과를 표시합니다.
사람이 PDF에서 숫자를 수동 복사하다가 페이지 참조나 표 맥락을 잃습니다.
/doc-parser를 실행해 문서에서 구조화 필드, 표, 근거 메모, 검토 플래그를 추출합니다.
대상
기능
경쟁사 PDF에서 가격, 패키지, 주장, 증거를 추출합니다.
PDF와 DOCX를 분석 보고서용 원천 표로 바꿉니다.
제출 문서를 구조화된 검토 필드로 변환합니다.
작동 방식
문서 또는 추출된 파일 내용과 필요한 정보를 제공합니다.
텍스트, 제목, 표, 양식, 레이아웃 단서를 파싱합니다.
구조화 필드, 표, 인용, 페이지 참조를 반환합니다.
누락, 모호함, 낮은 신뢰도의 추출 결과를 강조합니다.
파싱된 내용을 분석, 보고, CRM 또는 데이터 입력에 맞게 준비합니다.
입력 옵션
PDF, DOCX, 스크린샷, 스캔 또는 추출 텍스트입니다.
예시
문서: 구매 조달 패킷에 포함된 LearnPro Enterprise 가격 PDF. 추출 필요: - 티어 이름 - 사용자당 가격 - 구현 비용 - SSO와 관리자 제어 조건 - 계약 최소 조건 - 페이지 참조 중요: 정확한 가격을 요약으로 없애지 말고 페이지 참조와 불확실한 필드를 유지하세요.
| 필드 | 추출 값 | 페이지 | 신뢰도 | |---|---|---:|---| | 제품 티어 | 엔터프라이즈 플러스 | 2 | 높음 | | 좌석 가격 | $31/사용자/월, 연간 계약 | 3 | 높음 | | 구현 비용 | $18,000 일회성 | 3 | 높음 | | SSO | 엔터프라이즈 플러스에 포함 | 4 | 중간 | | 관리자 제어 | 고급 관리자 제어 포함 | 4 | 중간 | | 계약 최소 | 250석 | 3 | 높음 |
SSO와 관리자 제어 조건은 가격 표가 아니라 기능 표에 있습니다. 구매자의 지역과 계약 버전에 이 PDF가 적용되는지 조달팀이 확인하기 전까지는 포함 항목으로 단정하지 마세요.
가격, 구현 비용, 좌석 최소 조건을 가격 비교에 사용하세요. 3-4페이지의 정확한 문구는 제품 마케팅과 재무팀 검토용 출처 근거로 첨부합니다.
PDF가 최신인지, 할인이 제외되었는지, 손글씨나 스캔 주석을 놓치지 않았는지 확인합니다.
개선되는 지표
지원 도구
문서 파서을(를) 사용해 보시겠어요?
시작 방법을 선택하세요.
이 스킬을 컴퓨터에 로컬로 설치하고 실행합니다.
컴퓨터에서 터미널을 열고 이 명령을 붙여넣으세요:
이 명령은 스킬과 모든 파일을 컴퓨터에 다운로드합니다:
모든 프로젝트에서 사용하려면 끝에 -g를 추가하세요.
Claude Code를 시작한 다음 명령을 입력하세요:
문서 파서 스킬
개요
이 스킬은 IBM의 최신 문서 이해 라이브러리인 docling을 사용해 고급 문서 파싱을 가능하게 합니다. 구조를 보존하고 표와 그림을 추출하며 다단 레이아웃을 처리하면서 복잡한 PDF, Word 문서, 이미지를 파싱합니다.
사용 방법
- 파싱할 문서를 제공합니다.
- 추출하려는 항목(텍스트, 표, 그림 등)을 지정합니다.
- 문서를 파싱하고 구조화된 데이터를 반환합니다.
예시 프롬프트:
- "이 PDF를 파싱하고 모든 표를 추출해줘"
- "이 학술 논문을 구조화된 markdown으로 변환해줘"
- "이 문서에서 그림과 캡션을 추출해줘"
- "문서 구조를 보존하면서 이 보고서를 파싱해줘"
도메인 지식
docling 기본
from docling.document_converter import DocumentConverter
# 변환기 초기화
converter = DocumentConverter()
# 문서 변환
result = converter.convert("document.pdf")
# 파싱된 콘텐츠 접근
doc = result.document
print(doc.export_to_markdown())
지원 형식
| 형식 | 확장자 | 메모 |
|---|---|---|
| 네이티브 및 스캔본 | ||
| Word | .docx | 전체 구조 보존 |
| PowerPoint | .pptx | 슬라이드를 섹션으로 처리 |
| 이미지 | .png, .jpg | OCR + 레이아웃 분석 |
| HTML | .html | 구조 보존 |
기본 사용법
from docling.document_converter import DocumentConverter
# 변환기 생성
converter = DocumentConverter()
# 단일 문서 변환
result = converter.convert("report.pdf")
# 문서 접근
doc = result.document
# 내보내기 옵션
markdown = doc.export_to_markdown()
text = doc.export_to_text()
json_doc = doc.export_to_dict()
고급 설정
from docling.document_converter import DocumentConverter
from docling.datamodel.base_models import InputFormat
from docling.datamodel.pipeline_options import PdfPipelineOptions
# 파이프라인 설정
pipeline_options = PdfPipelineOptions()
pipeline_options.do_ocr = True
pipeline_options.do_table_structure = True
pipeline_options.table_structure_options.do_cell_matching = True
# 옵션이 있는 변환기 생성
converter = DocumentConverter(
allowed_formats=[InputFormat.PDF, InputFormat.DOCX],
pdf_backend_options=pipeline_options
)
result = converter.convert("document.pdf")
문서 구조
# 문서 계층
doc = result.document
# 메타데이터 접근
print(doc.name)
print(doc.origin)
# 콘텐츠 순회
for element in doc.iterate_items():
print(f"Type: {element.type}")
print(f"Text: {element.text}")
if element.type == "table":
print(f"Rows: {len(element.data.table_cells)}")
표 추출
from docling.document_converter import DocumentConverter
import pandas as pd
def extract_tables(doc_path):
"""문서에서 모든 표를 추출합니다."""
converter = DocumentConverter()
result = converter.convert(doc_path)
doc = result.document
tables = []
for element in doc.iterate_items():
if element.type == "table":
# 표 데이터 가져오기
table_data = element.export_to_dataframe()
tables.append({
'page': element.prov[0].page_no if element.prov else None,
'dataframe': table_data
})
return tables
# 사용법
tables = extract_tables("report.pdf")
for i, table in enumerate(tables):
print(f"{table['page']}페이지의 표 {i+1}:")
print(table['dataframe'])
그림 추출
def extract_figures(doc_path, output_dir):
"""캡션이 있는 그림을 추출합니다."""
import os
converter = DocumentConverter()
result = converter.convert(doc_path)
doc = result.document
figures = []
os.makedirs(output_dir, exist_ok=True)
for element in doc.iterate_items():
if element.type == "picture":
figure_info = {
'caption': element.caption if hasattr(element, 'caption') else None,
'page': element.prov[0].page_no if element.prov else None,
}
# 이미지가 있으면 저장
if hasattr(element, 'image'):
img_path = os.path.join(output_dir, f"figure_{len(figures)+1}.png")
element.image.save(img_path)
figure_info['path'] = img_path
figures.append(figure_info)
return figures
다단 레이아웃 처리
from docling.document_converter import DocumentConverter
def parse_multicolumn(doc_path):
"""다단 레이아웃 문서를 파싱합니다."""
converter = DocumentConverter()
result = converter.convert(doc_path)
doc = result.document
# docling은 열 감지를 자동으로 처리합니다.
# 텍스트는 읽기 순서로 반환됩니다.
structured_content = []
for element in doc.iterate_items():
content_item = {
'type': element.type,
'text': element.text if hasattr(element, 'text') else None,
'level': element.level if hasattr(element, 'level') else None,
}
# 있으면 경계 상자 추가
if element.prov:
content_item['bbox'] = element.prov[0].bbox
content_item['page'] = element.prov[0].page_no
structured_content.append(content_item)
return structured_content
내보내기 형식
from docling.document_converter import DocumentConverter
converter = DocumentConverter()
result = converter.convert("document.pdf")
doc = result.document
# Markdown 내보내기
markdown = doc.export_to_markdown()
with open("output.md", "w") as f:
f.write(markdown)
# 일반 텍스트
text = doc.export_to_text()
# JSON/dict 형식
json_doc = doc.export_to_dict()
# HTML 형식(지원되는 경우)
# html = doc.export_to_html()
일괄 처리
from docling.document_converter import DocumentConverter
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
def batch_parse(input_dir, output_dir, max_workers=4):
"""여러 문서를 병렬로 파싱합니다."""
input_path = Path(input_dir)
output_path = Path(output_dir)
output_path.mkdir(exist_ok=True)
converter = DocumentConverter()
def process_single(doc_path):
try:
result = converter.convert(str(doc_path))
md = result.document.export_to_markdown()
out_file = output_path / f"{doc_path.stem}.md"
with open(out_file, 'w') as f:
f.write(md)
return {'file': str(doc_path), 'status': 'success'}
except Exception as e:
return {'file': str(doc_path), 'status': 'error', 'error': str(e)}
docs = list(input_path.glob('*.pdf')) + list(input_path.glob('*.docx'))
with ThreadPoolExecutor(max_workers=max_workers) as executor:
results = list(executor.map(process_single, docs))
return results
모범 사례
- 적절한 파이프라인 사용: 문서 유형에 맞게 설정합니다.
- 대형 문서 처리: 필요하면 청크로 처리합니다.
- 표 추출 검증: 복잡한 표는 검토가 필요할 수 있습니다.
- OCR 품질 확인: 스캔 문서에는 OCR을 활성화합니다.
- 결과 캐시: 재사용을 위해 파싱된 문서를 저장합니다.
일반 패턴
학술 논문 파서
def parse_academic_paper(pdf_path):
"""학술 논문 구조를 파싱합니다."""
converter = DocumentConverter()
result = converter.convert(pdf_path)
doc = result.document
paper = {
'title': None,
'abstract': None,
'sections': [],
'references': [],
'tables': [],
'figures': []
}
current_section = None
for element in doc.iterate_items():
text = element.text if hasattr(element, 'text') else ''
if element.type == 'title':
paper['title'] = text
elif element.type == 'heading':
if 'abstract' in text.lower():
current_section = 'abstract'
elif 'reference' in text.lower():
current_section = 'references'
else:
paper['sections'].append({
'title': text,
'content': ''
})
current_section = 'section'
elif element.type == 'paragraph':
if current_section == 'abstract':
paper['abstract'] = text
elif current_section == 'section' and paper['sections']:
paper['sections'][-1]['content'] += text + '\n'
elif element.type == 'table':
paper['tables'].append({
'caption': element.caption if hasattr(element, 'caption') else None,
'data': element.export_to_dataframe() if hasattr(element, 'export_to_dataframe') else None
})
return paper
보고서를 구조화 데이터로 변환
def parse_business_report(doc_path):
"""비즈니스 보고서를 구조화된 형식으로 파싱합니다."""
converter = DocumentConverter()
result = converter.convert(doc_path)
doc = result.document
report = {
'metadata': {
'title': None,
'date': None,
'author': None
},
'executive_summary': None,
'sections': [],
'key_metrics': [],
'recommendations': []
}
# 문서 구조 파싱
for element in doc.iterate_items():
# 문서 구조에 따라 파싱 로직 구현
pass
return report
예시
예시 1: 재무 보고서 파싱
from docling.document_converter import DocumentConverter
def parse_financial_report(pdf_path):
"""재무 보고서에서 구조화된 데이터를 추출합니다."""
converter = DocumentConverter()
result = converter.convert(pdf_path)
doc = result.document
financial_data = {
'income_statement': None,
'balance_sheet': None,
'cash_flow': None,
'notes': []
}
# 표 추출
tables = []
for element in doc.iterate_items():
if element.type == 'table':
table_df = element.export_to_dataframe()
# 표 유형 식별
if 'revenue' in str(table_df).lower() or 'income' in str(table_df).lower():
financial_data['income_statement'] = table_df
elif 'asset' in str(table_df).lower() or 'liabilities' in str(table_df).lower():
financial_data['balance_sheet'] = table_df
elif 'cash' in str(table_df).lower():
financial_data['cash_flow'] = table_df
else:
tables.append(table_df)
# 메모용 markdown 추출
financial_data['markdown'] = doc.export_to_markdown()
return financial_data
report = parse_financial_report('annual_report.pdf')
print("손익계산서:")
print(report['income_statement'])
예시 2: 기술 문서 파서
from docling.document_converter import DocumentConverter
def parse_technical_docs(doc_path):
"""기술 문서를 파싱합니다."""
converter = DocumentConverter()
result = converter.convert(doc_path)
doc = result.document
documentation = {
'title': None,
'version': None,
'sections': [],
'code_blocks': [],
'diagrams': []
}
current_section = None
for element in doc.iterate_items():
if element.type == 'title':
documentation['title'] = element.text
elif element.type == 'heading':
current_section = {
'title': element.text,
'level': element.level if hasattr(element, 'level') else 1,
'content': []
}
documentation['sections'].append(current_section)
elif element.type == 'code':
if current_section:
current_section['content'].append({
'type': 'code',
'content': element.text
})
documentation['code_blocks'].append(element.text)
elif element.type == 'picture':
documentation['diagrams'].append({
'page': element.prov[0].page_no if element.prov else None,
'caption': element.caption if hasattr(element, 'caption') else None
})
return documentation
docs = parse_technical_docs('api_documentation.pdf')
print(f"제목: {docs['title']}")
print(f"섹션 수: {len(docs['sections'])}")
예시 3: 계약서 분석
from docling.document_converter import DocumentConverter
def analyze_contract(pdf_path):
"""핵심 조항을 찾기 위해 계약 문서를 파싱합니다."""
converter = DocumentConverter()
result = converter.convert(pdf_path)
doc = result.document
contract = {
'parties': [],
'clauses': [],
'dates': [],
'amounts': [],
'full_text': doc.export_to_text()
}
import re
# 날짜 추출
date_pattern = r'\b\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b|\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]* \d{1,2},? \d{4}\b'
contract['dates'] = re.findall(date_pattern, contract['full_text'], re.IGNORECASE)
# 금액 추출
amount_pattern = r'\$[\d,]+(?:\.\d{2})?|\b\d+(?:,\d{3})*(?:\.\d{2})?\s*(?:USD|dollars)\b'
contract['amounts'] = re.findall(amount_pattern, contract['full_text'], re.IGNORECASE)
# 섹션을 조항으로 파싱
for element in doc.iterate_items():
if element.type == 'heading':
contract['clauses'].append({
'title': element.text,
'content': ''
})
elif element.type == 'paragraph' and contract['clauses']:
contract['clauses'][-1]['content'] += element.text + '\n'
return contract
contract_data = analyze_contract('agreement.pdf')
print(f"핵심 날짜: {contract_data['dates']}")
print(f"금액: {contract_data['amounts']}")
제한 사항
- 매우 큰 문서는 청크 처리가 필요할 수 있습니다.
- 손글씨 콘텐츠는 OCR 전처리가 필요합니다.
- 복잡한 중첩 표는 수동 검토가 필요할 수 있습니다.
- 일부 PDF 유형(암호화된 파일)은 지원되지 않습니다.
- 최상의 성능을 위해 GPU를 권장합니다.
설치
pip install docling
# 전체 기능용
pip install docling[all]
# OCR 지원용
pip install docling[ocr]
자료
참조 문서
═══════════════════════════════════════════════════════════════════════════════
CLAUDE OFFICE SKILL - 향상된 메타데이터 v2.0
═══════════════════════════════════════════════════════════════════════════════
기본 정보
name: doc-parser description: ">" version: "1.0" author: claude-office-skills license: MIT
분류
category: parsing tags:
- parsing
- extraction
- layout
- docling department: All
AI 모델 호환성
models: recommended: - claude-sonnet-4 - claude-opus-4 compatible: - claude-3-5-sonnet - gpt-4 - gpt-4o
MCP 도구 연동
mcp: server: office-mcp tools: - analyze_document_structure - extract_text_from_pdf
스킬 역량
capabilities:
- document_parsing
- layout_analysis
언어 지원
languages:
- en
- zh
문서 파서 스킬
개요
이 스킬은 IBM의 최신 문서 이해 라이브러리인 docling을 사용해 고급 문서 파싱을 가능하게 합니다. 구조를 보존하고 표와 그림을 추출하며 다단 레이아웃을 처리하면서 복잡한 PDF, Word 문서, 이미지를 파싱합니다.
사용 방법
- 파싱할 문서를 제공합니다.
- 추출하려는 항목(텍스트, 표, 그림 등)을 지정합니다.
- 문서를 파싱하고 구조화된 데이터를 반환합니다.
예시 프롬프트:
- "이 PDF를 파싱하고 모든 표를 추출해줘"
- "이 학술 논문을 구조화된 markdown으로 변환해줘"
- "이 문서에서 그림과 캡션을 추출해줘"
- "문서 구조를 보존하면서 이 보고서를 파싱해줘"
도메인 지식
docling 기본
from docling.document_converter import DocumentConverter
# 변환기 초기화
converter = DocumentConverter()
# 문서 변환
result = converter.convert("document.pdf")
# 파싱된 콘텐츠 접근
doc = result.document
print(doc.export_to_markdown())
지원 형식
| 형식 | 확장자 | 메모 |
|---|---|---|
| 네이티브 및 스캔본 | ||
| Word | .docx | 전체 구조 보존 |
| PowerPoint | .pptx | 슬라이드를 섹션으로 처리 |
| 이미지 | .png, .jpg | OCR + 레이아웃 분석 |
| HTML | .html | 구조 보존 |
기본 사용법
from docling.document_converter import DocumentConverter
# 변환기 생성
converter = DocumentConverter()
# 단일 문서 변환
result = converter.convert("report.pdf")
# 문서 접근
doc = result.document
# 내보내기 옵션
markdown = doc.export_to_markdown()
text = doc.export_to_text()
json_doc = doc.export_to_dict()
고급 설정
from docling.document_converter import DocumentConverter
from docling.datamodel.base_models import InputFormat
from docling.datamodel.pipeline_options import PdfPipelineOptions
# 파이프라인 설정
pipeline_options = PdfPipelineOptions()
pipeline_options.do_ocr = True
pipeline_options.do_table_structure = True
pipeline_options.table_structure_options.do_cell_matching = True
# 옵션이 있는 변환기 생성
converter = DocumentConverter(
allowed_formats=[InputFormat.PDF, InputFormat.DOCX],
pdf_backend_options=pipeline_options
)
result = converter.convert("document.pdf")
문서 구조
# 문서 계층
doc = result.document
# 메타데이터 접근
print(doc.name)
print(doc.origin)
# 콘텐츠 순회
for element in doc.iterate_items():
print(f"Type: {element.type}")
print(f"Text: {element.text}")
if element.type == "table":
print(f"Rows: {len(element.data.table_cells)}")
표 추출
from docling.document_converter import DocumentConverter
import pandas as pd
def extract_tables(doc_path):
"""문서에서 모든 표를 추출합니다."""
converter = DocumentConverter()
result = converter.convert(doc_path)
doc = result.document
tables = []
for element in doc.iterate_items():
if element.type == "table":
# 표 데이터 가져오기
table_data = element.export_to_dataframe()
tables.append({
'page': element.prov[0].page_no if element.prov else None,
'dataframe': table_data
})
return tables
# 사용법
tables = extract_tables("report.pdf")
for i, table in enumerate(tables):
print(f"{table['page']}페이지의 표 {i+1}:")
print(table['dataframe'])
그림 추출
def extract_figures(doc_path, output_dir):
"""캡션이 있는 그림을 추출합니다."""
import os
converter = DocumentConverter()
result = converter.convert(doc_path)
doc = result.document
figures = []
os.makedirs(output_dir, exist_ok=True)
for element in doc.iterate_items():
if element.type == "picture":
figure_info = {
'caption': element.caption if hasattr(element, 'caption') else None,
'page': element.prov[0].page_no if element.prov else None,
}
# 이미지가 있으면 저장
if hasattr(element, 'image'):
img_path = os.path.join(output_dir, f"figure_{len(figures)+1}.png")
element.image.save(img_path)
figure_info['path'] = img_path
figures.append(figure_info)
return figures
다단 레이아웃 처리
from docling.document_converter import DocumentConverter
def parse_multicolumn(doc_path):
"""다단 레이아웃 문서를 파싱합니다."""
converter = DocumentConverter()
result = converter.convert(doc_path)
doc = result.document
# docling은 열 감지를 자동으로 처리합니다.
# 텍스트는 읽기 순서로 반환됩니다.
structured_content = []
for element in doc.iterate_items():
content_item = {
'type': element.type,
'text': element.text if hasattr(element, 'text') else None,
'level': element.level if hasattr(element, 'level') else None,
}
# 있으면 경계 상자 추가
if element.prov:
content_item['bbox'] = element.prov[0].bbox
content_item['page'] = element.prov[0].page_no
structured_content.append(content_item)
return structured_content
내보내기 형식
from docling.document_converter import DocumentConverter
converter = DocumentConverter()
result = converter.convert("document.pdf")
doc = result.document
# Markdown 내보내기
markdown = doc.export_to_markdown()
with open("output.md", "w") as f:
f.write(markdown)
# 일반 텍스트
text = doc.export_to_text()
# JSON/dict 형식
json_doc = doc.export_to_dict()
# HTML 형식(지원되는 경우)
# html = doc.export_to_html()
일괄 처리
from docling.document_converter import DocumentConverter
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
def batch_parse(input_dir, output_dir, max_workers=4):
"""여러 문서를 병렬로 파싱합니다."""
input_path = Path(input_dir)
output_path = Path(output_dir)
output_path.mkdir(exist_ok=True)
converter = DocumentConverter()
def process_single(doc_path):
try:
result = converter.convert(str(doc_path))
md = result.document.export_to_markdown()
out_file = output_path / f"{doc_path.stem}.md"
with open(out_file, 'w') as f:
f.write(md)
return {'file': str(doc_path), 'status': 'success'}
except Exception as e:
return {'file': str(doc_path), 'status': 'error', 'error': str(e)}
docs = list(input_path.glob('*.pdf')) + list(input_path.glob('*.docx'))
with ThreadPoolExecutor(max_workers=max_workers) as executor:
results = list(executor.map(process_single, docs))
return results
모범 사례
- 적절한 파이프라인 사용: 문서 유형에 맞게 설정합니다.
- 대형 문서 처리: 필요하면 청크로 처리합니다.
- 표 추출 검증: 복잡한 표는 검토가 필요할 수 있습니다.
- OCR 품질 확인: 스캔 문서에는 OCR을 활성화합니다.
- 결과 캐시: 재사용을 위해 파싱된 문서를 저장합니다.
일반 패턴
학술 논문 파서
def parse_academic_paper(pdf_path):
"""학술 논문 구조를 파싱합니다."""
converter = DocumentConverter()
result = converter.convert(pdf_path)
doc = result.document
paper = {
'title': None,
'abstract': None,
'sections': [],
'references': [],
'tables': [],
'figures': []
}
current_section = None
for element in doc.iterate_items():
text = element.text if hasattr(element, 'text') else ''
if element.type == 'title':
paper['title'] = text
elif element.type == 'heading':
if 'abstract' in text.lower():
current_section = 'abstract'
elif 'reference' in text.lower():
current_section = 'references'
else:
paper['sections'].append({
'title': text,
'content': ''
})
current_section = 'section'
elif element.type == 'paragraph':
if current_section == 'abstract':
paper['abstract'] = text
elif current_section == 'section' and paper['sections']:
paper['sections'][-1]['content'] += text + '\n'
elif element.type == 'table':
paper['tables'].append({
'caption': element.caption if hasattr(element, 'caption') else None,
'data': element.export_to_dataframe() if hasattr(element, 'export_to_dataframe') else None
})
return paper
보고서를 구조화 데이터로 변환
def parse_business_report(doc_path):
"""비즈니스 보고서를 구조화된 형식으로 파싱합니다."""
converter = DocumentConverter()
result = converter.convert(doc_path)
doc = result.document
report = {
'metadata': {
'title': None,
'date': None,
'author': None
},
'executive_summary': None,
'sections': [],
'key_metrics': [],
'recommendations': []
}
# 문서 구조 파싱
for element in doc.iterate_items():
# 문서 구조에 따라 파싱 로직 구현
pass
return report
예시
예시 1: 재무 보고서 파싱
from docling.document_converter import DocumentConverter
def parse_financial_report(pdf_path):
"""재무 보고서에서 구조화된 데이터를 추출합니다."""
converter = DocumentConverter()
result = converter.convert(pdf_path)
doc = result.document
financial_data = {
'income_statement': None,
'balance_sheet': None,
'cash_flow': None,
'notes': []
}
# 표 추출
tables = []
for element in doc.iterate_items():
if element.type == 'table':
table_df = element.export_to_dataframe()
# 표 유형 식별
if 'revenue' in str(table_df).lower() or 'income' in str(table_df).lower():
financial_data['income_statement'] = table_df
elif 'asset' in str(table_df).lower() or 'liabilities' in str(table_df).lower():
financial_data['balance_sheet'] = table_df
elif 'cash' in str(table_df).lower():
financial_data['cash_flow'] = table_df
else:
tables.append(table_df)
# 메모용 markdown 추출
financial_data['markdown'] = doc.export_to_markdown()
return financial_data
report = parse_financial_report('annual_report.pdf')
print("손익계산서:")
print(report['income_statement'])
예시 2: 기술 문서 파서
from docling.document_converter import DocumentConverter
def parse_technical_docs(doc_path):
"""기술 문서를 파싱합니다."""
converter = DocumentConverter()
result = converter.convert(doc_path)
doc = result.document
documentation = {
'title': None,
'version': None,
'sections': [],
'code_blocks': [],
'diagrams': []
}
current_section = None
for element in doc.iterate_items():
if element.type == 'title':
documentation['title'] = element.text
elif element.type == 'heading':
current_section = {
'title': element.text,
'level': element.level if hasattr(element, 'level') else 1,
'content': []
}
documentation['sections'].append(current_section)
elif element.type == 'code':
if current_section:
current_section['content'].append({
'type': 'code',
'content': element.text
})
documentation['code_blocks'].append(element.text)
elif element.type == 'picture':
documentation['diagrams'].append({
'page': element.prov[0].page_no if element.prov else None,
'caption': element.caption if hasattr(element, 'caption') else None
})
return documentation
docs = parse_technical_docs('api_documentation.pdf')
print(f"제목: {docs['title']}")
print(f"섹션 수: {len(docs['sections'])}")
예시 3: 계약서 분석
from docling.document_converter import DocumentConverter
def analyze_contract(pdf_path):
"""핵심 조항을 찾기 위해 계약 문서를 파싱합니다."""
converter = DocumentConverter()
result = converter.convert(pdf_path)
doc = result.document
contract = {
'parties': [],
'clauses': [],
'dates': [],
'amounts': [],
'full_text': doc.export_to_text()
}
import re
# 날짜 추출
date_pattern = r'\b\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b|\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]* \d{1,2},? \d{4}\b'
contract['dates'] = re.findall(date_pattern, contract['full_text'], re.IGNORECASE)
# 금액 추출
amount_pattern = r'\$[\d,]+(?:\.\d{2})?|\b\d+(?:,\d{3})*(?:\.\d{2})?\s*(?:USD|dollars)\b'
contract['amounts'] = re.findall(amount_pattern, contract['full_text'], re.IGNORECASE)
# 섹션을 조항으로 파싱
for element in doc.iterate_items():
if element.type == 'heading':
contract['clauses'].append({
'title': element.text,
'content': ''
})
elif element.type == 'paragraph' and contract['clauses']:
contract['clauses'][-1]['content'] += element.text + '\n'
return contract
contract_data = analyze_contract('agreement.pdf')
print(f"핵심 날짜: {contract_data['dates']}")
print(f"금액: {contract_data['amounts']}")
제한 사항
- 매우 큰 문서는 청크 처리가 필요할 수 있습니다.
- 손글씨 콘텐츠는 OCR 전처리가 필요합니다.
- 복잡한 중첩 표는 수동 검토가 필요할 수 있습니다.
- 일부 PDF 유형(암호화된 파일)은 지원되지 않습니다.
- 최상의 성능을 위해 GPU를 권장합니다.
설치
pip install docling
# 전체 기능용
pip install docling[all]
# OCR 지원용
pip install docling[ocr]