wing-ops/backend/scripts/hns-import
2026-04-17 09:38:06 +09:00
..
extract-excel.py feat(hns): HNS 물질 DB 확장 및 데이터 구조 개선 2026-04-17 09:38:06 +09:00
extract-images.py feat(hns): HNS 물질 DB 확장 및 데이터 구조 개선 2026-04-17 09:38:06 +09:00
merge-batch.py feat(hns): HNS 물질 DB 확장 및 데이터 구조 개선 2026-04-17 09:38:06 +09:00
merge-data.ts feat(hns): HNS 물질 DB 확장 및 데이터 구조 개선 2026-04-17 09:38:06 +09:00
ocr-claude-vision.ts feat(hns): HNS 물질 DB 확장 및 데이터 구조 개선 2026-04-17 09:38:06 +09:00
ocr-local.py feat(hns): HNS 물질 DB 확장 및 데이터 구조 개선 2026-04-17 09:38:06 +09:00
README.md feat(hns): HNS 물질 DB 확장 및 데이터 구조 개선 2026-04-17 09:38:06 +09:00
requirements.txt feat(hns): HNS 물질 DB 확장 및 데이터 구조 개선 2026-04-17 09:38:06 +09:00

HNS 물질 Import 파이프라인

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

파이프라인 구조

[Excel xlsm]
   ├─ (1) extract-excel.py   → out/base.json      (1,345종 기본 정보)
   └─ (2) extract-images.py  → out/images/*.png   (225종 상세 카드 이미지)
                                  ↓
                               (3) ocr-images.ts  → out/ocr.json  (Claude Vision → 물성/위험도/EmS JSON)
                                                                 ↓
                                            (4) merge-data.ts  → frontend/src/data/hnsSubstanceData.json
                                                                              ↓
                                                           (5) tsx src/db/seedHns.ts  → HNS_SUBSTANCE 테이블

전제 조건

  • Python 3.9+ with openpyxl
  • Node.js 20
  • ANTHROPIC_API_KEY 환경변수 (Claude Vision API)
  • Excel 원본 파일: C:\Projects\MeterialDB\유해물질 화물적부도 검색툴.xlsm

실행 순서

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

2) 이미지 225개 추출

python scripts/hns-import/extract-images.py
  • 출력:
    • scripts/hns-import/out/images/{nameKr}.png
    • scripts/hns-import/out/image-map.json (파일명↔시트명 매핑)

3) Claude Vision OCR

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

4) 최종 JSON 병합

npx tsx scripts/hns-import/merge-data.ts
  • 입력: out/base.json + out/ocr.json
  • 출력: frontend/src/data/hnsSubstanceData.json (전량 덮어쓰기)

5) DB 재시드

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

재실행 안내

  • out/ 디렉토리는 .gitignore 처리되어 커밋되지 않음
  • OCR 결과는 비결정적이므로 재실행 시 약간 달라질 수 있음
  • 비용 절감을 위해 OCR 결과는 보존하고 ocr-images.ts --resume 로 실패 항목만 재시도 가능

비용/시간 가이드

  • 이미지 225장 × Claude Sonnet 4.6 기준 약 $3~10
  • 전체 파이프라인: Excel 파싱 ~30초, 이미지 추출 ~10초, OCR ~10~20분, 병합/시드 ~1분

알려진 이슈 (후속 작업 필요)

1) OCR ↔ base.json 국문명 매칭 실패 (136건)

merge-data.ts 실행 시 base.json의 국문명과 ocr.json 키 표기가 달라 상세정보가 연결되지 않는 물질이 다수 존재. 실제 514종 중 상세 정보 보유는 73종 수준.

예시:

base.json 국문명 ocr.json 키
1메톡시2프로판올 1-메톡시-2프로판올
c810이소알코올 (C8-10)이소 알코올
메탄올 (OCR 없음, 이미지 누락)
가솔린 휘발유 (동의어)

원인:

  • 하이픈/공백/괄호 제거 수준 차이 (Excel 시트명과 이미지 파일명 추출 로직 불일치)
  • 동의어 처리 미흡 (동의어 시트 215개 활용 필요)
  • OCR 대상 225종 외 나머지 1,120종은 기본정보만 존재

권장 해결 방향:

  • merge-data.ts 에 정규화 함수 추가 (공백/하이픈/괄호 제거 후 매칭)
  • base.json 의 동의어(synonyms) 배열을 역인덱스로 활용해 OCR 키와 교차 매칭
  • 매칭 실패 목록을 out/merge-unmatched.json 으로 출력하여 수동 검토

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

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

영향:

  • CAS_NO, UN_NO 검색 시 두 번째 이후 번호로는 매칭 불가
  • 프론트엔드 표시 시 JSONB의 원본 값을 참조해야 함

권장 해결 방향:

  • extract-excel.py 에서 복수 CAS/UN 을 배열로 분리 저장
  • 스키마에 CAS_NO_LIST TEXT[], UN_NO_LIST TEXT[] 추가 후 GIN 인덱스 구성

3) MSDS 요약시트 포맷 이미지 (약 5건)

원본 xlsm 일부 시트는 표준 HNS 카드가 아닌 KOSHA MSDS 요약시트 포맷으로, 저해상도 + 필드 구조 상이로 OCR 정확도가 떨어짐.

해당 물질: 프로필벤젠, 프르푸필 알콜, 프로필렌 클리콜 알긴산, 휘발유, 헥사메틸렌 디이소시안산

권장 해결 방향:

  • ANTHROPIC_API_KEY 설정 후 HNS_OCR_ONLY 로 해당 5종만 재OCR
  • 이미지 누락 필드는 화학 문헌값(ICSC, PubChem)으로 보강