PyMuPDF 및 pdfplumber로 PDF 파싱
프로그래밍으로 PDF에서 텍스트, 표, 메타데이터를 추출합니다.
PyMuPDF 및 pdfplumber로 PDF 파싱은(는) CoddyKit의 무료 AI Agents 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Agents 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.
PDF 구문 분석이 간단하지 않은 이유
PDF는 데이터 형식이 아니라 표시 형식입니다. 텍스트가 논리적인 문단이 아니라 위치가 지정된 글리프로 저장됩니다. 의미 있는 텍스트를 추출하려면 레이아웃, 읽기 순서, 글꼴 속성을 이해하고 여러 열 레이아웃, 머리글과 바닥글, 포함된 이미지 같은 예외 상황을 처리해야 합니다.
대표적인 두 라이브러리는 PyMuPDF(속도)와 pdfplumber(표 추출)입니다.
PyMuPDF 기초
PyMuPDF(fitz로 가져옴)는 가장 빠른 Python PDF 라이브러리입니다. 텍스트 추출, 메타데이터, 이미지, 렌더링을 처리합니다. pip install pymupdf로 설치합니다.
import fitz # PyMuPDF
# Open a PDF
doc = fitz.open('document.pdf')
print(f'Pages: {len(doc)}')
print(f'Metadata: {doc.metadata}')
# Extract text from all pages
full_text = ''
for page_num in range(len(doc)):
page = doc[page_num]
text = page.get_text() # plain text extraction
full_text += f'--- Page {page_num + 1} ---\n{text}\n'
doc.close()
print(full_text[:500])PyMuPDF 텍스트 추출 모드
page.get_text()는 다양한 출력 형식을 지원합니다. 일반 텍스트에는 'text', 경계 상자가 포함된 텍스트 블록에는 'blocks', 글꼴 이름과 크기를 비롯한 풍부한 구조화된 출력에는 'dict'를 사용합니다.
import fitz
doc = fitz.open('report.pdf')
page = doc[0]
# Mode 1: plain text
plain = page.get_text('text')
# Mode 2: blocks (each block has bbox + text)
blocks = page.get_text('blocks')
for block in blocks:
x0, y0, x1, y1, text, block_no, block_type = block
if block_type == 0: # text block (1 = image)
print(f'Block at ({x0:.0f},{y0:.0f}): {text[:80]}')
# Mode 3: dict (full detail including font info)
page_dict = page.get_text('dict')
for block in page_dict['blocks']:
if block.get('type') == 0: # text
for line in block['lines']:
for span in line['spans']:
print(f"Font: {span['font']}, Size: {span['size']:.1f}, Text: {span['text']}")
doc.close()페이지 메타데이터 추출
페이지 메타데이터는 에이전트가 문서 구조를 이해하는 데 도움이 됩니다. 페이지 수, 문서 제목, 작성자, 생성 날짜, 페이지 크기 등이 이에 해당합니다. PyMuPDF는 이 모든 정보를 제공합니다.
import fitz
def extract_pdf_metadata(filepath):
doc = fitz.open(filepath)
meta = doc.metadata
info = {
'title': meta.get('title', 'Unknown'),
'author': meta.get('author', 'Unknown'),
'subject': meta.get('subject', ''),
'creator': meta.get('creator', ''),
'created': meta.get('creationDate', ''),
'modified': meta.get('modDate', ''),
'pages': len(doc),
'page_size': {
'width': doc[0].rect.width,
'height': doc[0].rect.height
}
}
doc.close()
return info
meta = extract_pdf_metadata('contract.pdf')
print(f"Title: {meta['title']}, Pages: {meta['pages']}")표 추출을 위한 pdfplumber
pdfplumber는 PDF에서 표를 추출하는 데 뛰어납니다. 기하학적 분석을 사용하여 명시적인 표 구조 표시가 없는 PDF에서도 셀 경계를 감지합니다.
pip install pdfplumber로 설치합니다.
import pdfplumber
with pdfplumber.open('financial_report.pdf') as pdf:
for page_num, page in enumerate(pdf.pages):
tables = page.extract_tables()
for table_idx, table in enumerate(tables):
print(f'Page {page_num+1}, Table {table_idx+1}:')
# table is a list of rows; each row is a list of cell strings
headers = table[0]
for row in table[1:]:
row_dict = dict(zip(headers, row))
print(row_dict)pdfplumber 표 설정
pdfplumber의 표 추출은 설정을 조정하여 다양한 표 스타일에 대응할 수 있습니다. 명시적인 선, 공백으로 구분된 열, 혼합 레이아웃 등을 처리할 수 있습니다.
import pdfplumber
# Custom table settings for borderless tables
table_settings = {
'vertical_strategy': 'text', # 'lines', 'lines_strict', 'text', 'explicit'
'horizontal_strategy': 'text',
'snap_tolerance': 5,
'join_tolerance': 3,
'edge_min_length': 50,
'min_words_vertical': 3,
'min_words_horizontal': 1
}
with pdfplumber.open('nolines_table.pdf') as pdf:
page = pdf.pages[0]
table = page.extract_table(table_settings)
if table:
import csv
import io
output = io.StringIO()
writer = csv.writer(output)
writer.writerows(table)
csv_string = output.getvalue()
print(csv_string[:300])여러 열 레이아웃 처리
학술 논문과 신문은 여러 열 레이아웃을 사용합니다. 단순한 텍스트 추출은 열을 왼쪽에서 오른쪽으로 가로질러 읽기 때문에 텍스트가 뒤섞입니다. 먼저 텍스트 블록을 열별로 정렬하여 이 문제를 해결합니다.
import fitz
def extract_multicolumn_text(page, n_columns=2):
page_width = page.rect.width
col_width = page_width / n_columns
blocks = page.get_text('blocks')
# Filter text blocks only
text_blocks = [b for b in blocks if b[6] == 0]
# Assign each block to a column based on x position
columns = [[] for _ in range(n_columns)]
for block in text_blocks:
x0 = block[0]
col_idx = min(int(x0 / col_width), n_columns - 1)
columns[col_idx].append(block)
# Sort each column by vertical position
for col in columns:
col.sort(key=lambda b: b[1]) # sort by y0
# Read columns left to right
full_text = ''
for col in columns:
for block in col:
full_text += block[4] + '\n'
return full_text머리글과 바닥글 필터링
PDF의 머리글과 바닥글은 모든 페이지에 반복되어 추출된 텍스트를 오염시킵니다. 페이지에서 세로 위치가 위쪽 또는 아래쪽 10%에 해당하는지 확인하여 머리글과 바닥글을 식별하고 내용 추출에서 제외합니다.
import fitz
def extract_without_headers_footers(page, margin_ratio=0.08):
page_height = page.rect.height
top_margin = page_height * margin_ratio
bottom_margin = page_height * (1 - margin_ratio)
blocks = page.get_text('blocks')
content_blocks = []
for block in blocks:
x0, y0, x1, y1, text, block_no, block_type = block
if block_type != 0:
continue # skip image blocks
# Skip blocks in header or footer zone
if y0 < top_margin or y1 > bottom_margin:
continue
content_blocks.append(text)
return '\n'.join(content_blocks)에이전트를 위한 PDF 텍스트를 청크로 나누기
임베딩과 검색을 위해 긴 PDF는 청크로 나누어야 합니다. 문단, 섹션 또는 페이지와 같은 자연스러운 경계에서 나누세요. 문장 중간에서 맥락이 끊기지 않도록 청크 사이에 겹치는 부분을 포함하세요.
import fitz
def pdf_to_chunks(filepath, chunk_size=1000, overlap=200):
doc = fitz.open(filepath)
chunks = []
for page_num in range(len(doc)):
page = doc[page_num]
page_text = page.get_text()
# Split into chunks with overlap
start = 0
while start < len(page_text):
end = start + chunk_size
chunk = page_text[start:end]
chunks.append({
'text': chunk,
'page': page_num + 1,
'char_start': start,
'source': filepath
})
start += chunk_size - overlap # overlap
doc.close()
return chunks
chunks = pdf_to_chunks('research_paper.pdf')
print(f'Total chunks: {len(chunks)}')
print(f'Sample: {chunks[0]["text"][:200]}')PyMuPDF와 pdfplumber 결합하기
텍스트 추출에는 PyMuPDF(더 빠름)를 사용하고, 표 감지에는 pdfplumber(더 정확함)를 사용하세요. 결합된 추출기는 각 페이지에서 두 작업을 모두 실행하고, 텍스트와 표가 분리된 구조화된 콘텐츠를 반환합니다.
import fitz
import pdfplumber
def full_pdf_extract(filepath):
result = {'text_by_page': [], 'tables': []}
# Text extraction with PyMuPDF
doc = fitz.open(filepath)
for i in range(len(doc)):
text = extract_without_headers_footers(doc[i])
result['text_by_page'].append({'page': i + 1, 'text': text})
doc.close()
# Table extraction with pdfplumber
with pdfplumber.open(filepath) as pdf:
for page_num, page in enumerate(pdf.pages):
tables = page.extract_tables()
for t in tables:
result['tables'].append({
'page': page_num + 1,
'headers': t[0] if t else [],
'rows': t[1:] if t and len(t) > 1 else []
})
return result추출한 텍스트를 파일에 저장하기
PDF에서 텍스트를 추출한 후에는 후속 에이전트가 사용할 수 있는 형식으로 저장하세요. 일반 텍스트 파일은 임베딩 처리 과정에 적합하고, JSON은 인용 추적에 필요한 페이지 구조를 보존합니다.
import json, os
class FakePage:
def __init__(self, text): self.text = text
def get_text(self): return self.text
class FakeDoc(list):
def close(self): pass
def fitz_open(path):
return FakeDoc([FakePage('Page 1 text'), FakePage('Page 2 text')])
def pdf_to_text_file(pdf_path, output_dir):
doc = fitz_open(pdf_path)
base = os.path.splitext(os.path.basename(pdf_path))[0]
txt_path = os.path.join(output_dir, base + '.txt')
with open(txt_path, 'w', encoding='utf-8') as f:
for i, page in enumerate(doc):
f.write(f'--- Page {i+1} ---\n{page.get_text()}\n')
json_path = os.path.join(output_dir, base + '.json')
pages = [{'page': i+1, 'text': p.get_text()} for i, p in enumerate(doc)]
with open(json_path, 'w') as f:
json.dump({'source': pdf_path, 'pages': pages}, f, indent=2)
doc.close()
print(f'Saved: {txt_path} and {json_path}')
return txt_path, json_path
pdf_to_text_file('sample.pdf', '.')지식 확인
PDF 파일에서 표를 추출하는 데 가장 적합한 파이썬 라이브러리는 무엇입니까?
복습: PyMuPDF와 pdfplumber를 사용한 PDF 구문 분석
PyMuPDF(fitz)는 텍스트 추출, 메타데이터 처리, 다단 레이아웃 처리에 적합한 빠른 선택지입니다. pdfplumber는 구성 가능한 기하학적 전략을 사용한 표 추출에 뛰어납니다.
핵심 기법은 다음과 같습니다. 위치를 고려한 추출에는 get_text('blocks')를 사용하고, 세로 위치를 기준으로 머리글과 바닥글을 필터링하며, 열별로 블록을 정렬해 다단 레이아웃을 처리하세요. 에이전트 검색 시스템을 위해 텍스트를 겹치는 부분과 함께 청크로 나누세요. 최상의 결과를 얻으려면 두 라이브러리를 결합하세요.
AI 튜터와 함께 AI Agents을(를) 배우세요 — 무료
브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.
- 코스
- 60
- 레슨
- 239
자주 묻는 질문
“PyMuPDF 및 pdfplumber로 PDF 파싱” 강의는 무료인가요?
네 — “PyMuPDF 및 pdfplumber로 PDF 파싱” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Agents 강의 전체를 잠금 해제할 수 있습니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.
“PyMuPDF 및 pdfplumber로 PDF 파싱”에서 뭘 배우나요?
프로그래밍으로 PDF에서 텍스트, 표, 메타데이터를 추출합니다. 브라우저에서 직접 실행하는 실습 코드로 AI Agents을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
AI Agents을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 AI Agents은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“PyMuPDF 및 pdfplumber로 PDF 파싱” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 AI Agents 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 AI Agents 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- PyMuPDF 및 pdfplumber로 PDF 파싱
- 스캔 문서를 위한 OCR
- 다중 문서 질의응답 에이전트
- 문서 분류 및 라우팅