install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/data-normalizer" ~/.claude/skills/majiayu000-claude-skill-registry-data-normalizer && rm -rf "$T"
manifest:
skills/data/data-normalizer/SKILL.mdsource content
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 활용)
- 저작권 준수: 내부 분석용으로만 사용