# 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 메타 시트 파싱 ```bash 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 실행 시만 필요) ```bash python scripts/hns-import/extract-images.py ``` - 출력: `out/images/{nameKr}.png`, `out/image-map.json` ### 2b) PDF 물질정보집 파싱 ★ 권장 ```bash 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 없을 때 보조) ```bash 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 병합 ```bash 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 재시드 ```bash cd backend npx tsx src/db/seedHns.ts ``` - 기존 `DELETE FROM HNS_SUBSTANCE` → 새 514종 INSERT ## 빠른 재실행 (PDF 추출 → 병합 → 시드) ```bash 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.ts`](../../../backend/src/db/seedHns.ts) 의 `firstToken()` 헬퍼로 첫 토큰만 검색 컬럼에 저장하고 원본 전체는 `DATA` JSONB에 보존.