wing-ops/backend/scripts/hns-import/README.md

4.9 KiB

HNS 물질 Import 파이프라인

C:\Projects\MeterialDB\유해물질 화물적부도 검색툴.xlsm 외부 자료를 HNS_SUBSTANCE DB로 변환하는 1회성 파이프라인.

파이프라인 구조

[Excel xlsm]                    [PDF 물질정보집 (193종)]
   ├─ (1) extract-excel.py          (2b) extract-pdf.py
   │      → out/base.json                → out/pdf-data.json
   └─ (2a) extract-images.py ──────────────────────────┐
           → out/images/*.png                           │
                ↓                                       │
           (3) ocr-images.ts                           │
               → out/ocr.json                          │
                          ↓                            ↓
                     (4) merge-data.ts  ←──────────────┘
                         → frontend/src/data/hnsSubstanceData.json
                                       ↓
                          (5) tsx src/db/seedHns.ts
                              → HNS_SUBSTANCE 테이블

병합 우선순위: pdf-data.json > base.json > ocr.json

전제 조건

  • Python 3.9+ with openpyxl, PyMuPDF(fitz)
  • Node.js 20
  • ANTHROPIC_API_KEY 환경변수 (Claude Vision API, OCR 실행 시에만 필요)
  • Excel 원본: C:\Projects\MeterialDB\유해물질 화물적부도 검색툴.xlsm
  • PDF 원본: C:\Projects\MeterialDB\해상화학사고_대응_물질정보집.pdf

실행 순서

1) Excel 메타 시트 파싱

cd backend
python scripts/hns-import/extract-excel.py
  • 입력: C:\Projects\MeterialDB\유해물질 화물적부도 검색툴.xlsm
  • 처리 시트: 화물적부도 화물코드(1,345개), 동의어(215개), IBC CODE(분류)
  • 출력: scripts/hns-import/out/base.json

2a) 이미지 225개 추출 (선택 — OCR 실행 시만 필요)

python scripts/hns-import/extract-images.py
  • 출력: out/images/{nameKr}.png, out/image-map.json

2b) PDF 물질정보집 파싱 ★ 권장

python scripts/hns-import/extract-pdf.py
  • 입력: C:\Projects\MeterialDB\해상화학사고_대응_물질정보집.pdf
  • 해양경찰청 발행 193종, 텍스트 직접 추출 (OCR 불필요)
  • 출력: scripts/hns-import/out/pdf-data.json

3) Claude Vision OCR (선택 — pdf-data.json 없을 때 보조)

export ANTHROPIC_API_KEY="sk-ant-..."
cd backend
npx tsx scripts/hns-import/ocr-images.ts
  • 이미지 한 장당 Claude API 1회 호출, 동시 5개 병렬
  • 출력: out/ocr.json { [nameKr]: OcrResult }

4) 최종 JSON 병합

cd backend
npx tsx scripts/hns-import/merge-data.ts
  • 입력: out/base.json + out/pdf-data.json + out/ocr.json (없으면 건너뜀)
  • 출력: frontend/src/data/hnsSubstanceData.json (전량 덮어쓰기)

5) DB 재시드

cd backend
npx tsx src/db/seedHns.ts
  • 기존 DELETE FROM HNS_SUBSTANCE → 새 514종 INSERT

빠른 재실행 (PDF 추출 → 병합 → 시드)

cd backend
python scripts/hns-import/extract-pdf.py && \
npx tsx scripts/hns-import/merge-data.ts && \
npx tsx src/db/seedHns.ts

현재 데이터 현황 (2024-04 기준)

항목 이전 (OCR) 현재 (PDF)
총 물질 수 514종 514종
상세정보 보유 (인화점 있음) 152종 195종
NFPA 코드 있음 ~150종 201종
CAS 번호 있음 ~380종 504종
해양거동 있음 ~0종 206종
한국어 유사명 있음 ~200종 449종

재실행 안내

  • out/ 디렉토리는 .gitignore 처리되어 커밋되지 않음
  • OCR 결과는 비결정적이므로 재실행 시 약간 달라질 수 있음
  • PDF 추출은 결정적(동일 입력 → 동일 출력)이므로 재실행 안전

알려진 이슈

1) PDF 매칭 실패 35종

PDF 국문명과 base.json 국문명이 달라 매칭되지 않는 항목이 35개 존재. out/pdf-unmatched.json에서 목록 확인 가능. 해당 항목은 OCR 데이터로 보조.

원인:

  • 영문제품명이 국문명으로 등록된 경우 (예: DER 383 Epoxy resin디이알 383)
  • 동일 CAS 충돌 (예: 컨덴세이트나프타가 같은 CAS)
  • 표기 차이 (예: 아이소파-G아이소파 G)

2) 2열 레이아웃 파싱 노이즈 (약 9건)

PDF 물질특성 블록이 2열로 구성되어 있어, 일부 항목에서 비중 값이 온도값으로 오추출될 수 있음. 영향 범위 최소 (벤젠 등 9종, 값이 100 이상이면 의심).

3) SEBC/CAS/UN 번호 varchar 길이 초과

base.json 생성 시 Excel에서 복수 CAS/UN 번호를 줄바꿈으로 결합해 저장하여, HNS_SUBSTANCE 테이블의 VARCHAR(20) 등 제약을 초과했음. 현재는 seedHns.tsfirstToken() 헬퍼로 첫 토큰만 검색 컬럼에 저장하고 원본 전체는 DATA JSONB에 보존.