| name | data-normalizer |
| description | 발굴조사 자료(논문/보고서/주변유적) 수집 및 메타데이터 정규화 |
| tags | archaeology, data-extraction, normalization, pipeline-step-1 |
Data Normalizer - 자료 수집 및 정규화
목적
논문/, 발굴조사보고서/, 주변유적/ 폴더의 모든 문서(PDF, HWP, DOCX, TXT)에서 텍스트와 메타데이터를 추출하여 통합 인덱스를 생성합니다.
입력
논문/폴더: 학술 논문 파일들발굴조사보고서/폴더: 발굴조사 보고서 파일들주변유적/폴더: 주변 유적 관련 자료들
처리 프로세스
1단계: 폴더 스캔 및 파일 목록 생성
# 지원 파일 형식: .pdf, .hwp, .docx, .doc, .txt
# 재귀적으로 모든 하위 폴더 탐색
2단계: 파일별 메타데이터 추출
각 파일에서 다음 정보를 추출:
- 식별자: UUID 또는 파일경로 기반 해시
- 경로: 상대 경로
- 제목: 문서 제목 (메타데이터 또는 첫 페이지에서 추출)
- 저자/기관: 작성자 또는 발간 기관
- 연도: 발간/작성 연도
- 지명: 조사지역, 유적명 (키워드 추출)
- 좌표: 위도/경도 (있는 경우)
- 시대: 청동기, 삼국시대, 통일신라 등
- 유구/유물 유형: 주거지, 수혈, 토기, 기와 등
- 초록/요약: 문서 요약 (있는 경우)
- 본문 텍스트 해시: 내용 변경 감지용
3단계: 텍스트 추출 및 구조화
- 페이지 단위 텍스트 추출
- 섹션 경계 보존 (목차, 장/절 제목 인식)
- 표와 그림 캡션 별도 필드화
- 참고문헌 섹션 식별 및 파싱
4단계: 출력 파일 생성
output/normalized/documents.jsonl (JSONL 형식)
{
"id": "doc_001",
"path": "논문/김철수_2020_청동기취락연구.pdf",
"title": "○○지역 청동기시대 취락 연구",
"author": "김철수",
"year": 2020,
"location": "○○시 △△동",
"coordinates": {"lat": 37.5665, "lon": 126.9780},
"period": ["청동기시대"],
"types": ["주거지", "수혈유구", "무문토기"],
"abstract": "본 연구는...",
"text_sections": [
{"section": "서론", "page": 1, "text": "..."},
{"section": "조사내용", "page": 5, "text": "..."}
],
"tables": [
{"caption": "유구 일람표", "page": 15, "content": "..."}
],
"references": ["이영희(2018)...", "박민수(2019)..."]
}
output/normalized/metadata.csv (스프레드시트용)
id,path,title,author,year,location,lat,lon,period,types,abstract_preview
doc_001,논문/...,○○지역 청동기...,김철수,2020,○○시,37.5665,126.9780,청동기시대,"주거지;수혈유구",본 연구는...
output/normalized/extraction_log.txt (처리 로그)
[2025-11-12 10:00:00] 처리 시작
[2025-11-12 10:00:01] 논문/ 폴더 스캔: 15개 파일 발견
[2025-11-12 10:00:05] doc_001 처리 완료: 논문/김철수_2020.pdf
[2025-11-12 10:00:10] 오류: doc_005 읽기 실패 (암호화된 PDF)
...
[2025-11-12 10:05:00] 처리 완료: 총 42개 파일, 성공 40개, 실패 2개
오류 처리
- 읽기 불가 파일 (암호화, 손상): 로그에 기록 후 건너뜀
- 메타데이터 부족: 추정값 사용 또는 "미상"으로 표기
- 좌표 없음: 지명 기반 지오코딩 시도 (선택)
품질 검증
- 추출된 파일 수와 실제 파일 수 일치 확인
- 필수 필드(제목, 연도, 지명) 누락률 < 10%
- 텍스트 추출 완전성: 페이지 수 vs 추출 섹션 수 비교
완료 후 다음 단계
다음 스킬 호출: similarity-matcher
전달 데이터: output/normalized/metadata.csv, output/normalized/documents.jsonl
기술 구현 가이드
PDF 텍스트 추출
import PyPDF2
import pdfplumber # 표 추출에 유용
def extract_pdf_text(file_path):
with pdfplumber.open(file_path) as pdf:
text_sections = []
for page_num, page in enumerate(pdf.pages, 1):
text = page.extract_text()
tables = page.extract_tables()
text_sections.append({
"page": page_num,
"text": text,
"tables": tables
})
return text_sections
HWP 파일 처리
import olefile # HWP 파일은 OLE 구조
# 또는 hwp5tools 사용
def extract_hwp_text(file_path):
# HWP는 복잡하므로 hwp5txt 명령줄 도구 활용 권장
import subprocess
result = subprocess.run(['hwp5txt', file_path],
capture_output=True, text=True)
return result.stdout
메타데이터 추출 (정규식 활용)
import re
def extract_metadata(text):
# 연도 추출 (19XX, 20XX)
year_match = re.search(r'(19|20)\d{2}', text)
year = int(year_match.group()) if year_match else None
# 좌표 추출 (N37°34'12" E126°58'30" 형식)
coord_pattern = r'N(\d+)°(\d+)\'(\d+)"\s*E(\d+)°(\d+)\'(\d+)"'
coord_match = re.search(coord_pattern, text)
# 시대 키워드
periods = []
period_keywords = ['청동기', '초기철기', '원삼국', '삼국시대',
'통일신라', '고려', '조선']
for keyword in period_keywords:
if keyword in text:
periods.append(keyword)
return {
'year': year,
'coordinates': parse_coordinates(coord_match) if coord_match else None,
'periods': periods
}
JSONL 저장
import json
def save_jsonl(data_list, output_path):
with open(output_path, 'w', encoding='utf-8') as f:
for item in data_list:
f.write(json.dumps(item, ensure_ascii=False) + '\n')
실행 명령
Claude에게 다음과 같이 요청하세요:
data-normalizer 스킬을 사용하여 논문/, 발굴조사보고서/, 주변유적/ 폴더의
모든 자료를 수집하고 메타데이터를 추출해주세요.
주의사항
- 대용량 파일(>100MB) 처리 시 메모리 관리 필요
- 한글 인코딩 문제: UTF-8, CP949, EUC-KR 모두 시도
- 스캔 PDF는 OCR 필요 (Tesseract 활용)
- 저작권 준수: 내부 분석용으로만 사용