Skip to content
Back to skills

Data Normalizer

ASecurity

발굴조사 자료(논문/보고서/주변유적) 수집 및 메타데이터 정규화

  • 666 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added February 8, 2026
developmentpython

Security analysis

A100/100

Scanned February 10, 2026

npx -y skills add majiayu000/claude-skill-registry --skill data-normalizer --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Data Normalizer?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Data Normalizer
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/majiayu000-data-normalizer/badge)](https://www.skillsdirectory.com/skills/majiayu000-data-normalizer)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: data-normalizer
description: 발굴조사 자료(논문/보고서/주변유적) 수집 및 메타데이터 정규화
tags: [archaeology, data-extraction, normalization, pipeline-step-1]
---

# Data Normalizer - 자료 수집 및 정규화

## 목적
논문/, 발굴조사보고서/, 주변유적/ 폴더의 모든 문서(PDF, HWP, DOCX, TXT)에서 텍스트와 메타데이터를 추출하여 통합 인덱스를 생성합니다.

## 입력
- `논문/` 폴더: 학술 논문 파일들
- `발굴조사보고서/` 폴더: 발굴조사 보고서 파일들
- `주변유적/` 폴더: 주변 유적 관련 자료들

## 처리 프로세스

### 1단계: 폴더 스캔 및 파일 목록 생성
```python
# 지원 파일 형식: .pdf, .hwp, .docx, .doc, .txt
# 재귀적으로 모든 하위 폴더 탐색
```

### 2단계: 파일별 메타데이터 추출
각 파일에서 다음 정보를 추출:
- **식별자**: UUID 또는 파일경로 기반 해시
- **경로**: 상대 경로
- **제목**: 문서 제목 (메타데이터 또는 첫 페이지에서 추출)
- **저자/기관**: 작성자 또는 발간 기관
- **연도**: 발간/작성 연도
- **지명**: 조사지역, 유적명 (키워드 추출)
- **좌표**: 위도/경도 (있는 경우)
- **시대**: 청동기, 삼국시대, 통일신라 등
- **유구/유물 유형**: 주거지, 수혈, 토기, 기와 등
- **초록/요약**: 문서 요약 (있는 경우)
- **본문 텍스트 해시**: 내용 변경 감지용

### 3단계: 텍스트 추출 및 구조화
- 페이지 단위 텍스트 추출
- 섹션 경계 보존 (목차, 장/절 제목 인식)
- 표와 그림 캡션 별도 필드화
- 참고문헌 섹션 식별 및 파싱

### 4단계: 출력 파일 생성
**output/normalized/documents.jsonl** (JSONL 형식)
```json
{
  "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** (스프레드시트용)
```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 텍스트 추출
```python
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 파일 처리
```python
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
```

### 메타데이터 추출 (정규식 활용)
```python
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 저장
```python
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 활용)
- 저작권 준수: 내부 분석용으로만 사용

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.