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

135 lines
5.1 KiB
Markdown
Raw Blame 히스토리

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 메타 시트 파싱
```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`
### 2) 이미지 225개 추출
```bash
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
```bash
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 병합
```bash
npx tsx scripts/hns-import/merge-data.ts
```
- 입력: `out/base.json` + `out/ocr.json`
- 출력: `frontend/src/data/hnsSubstanceData.json` (전량 덮어쓰기)
### 5) DB 재시드
```bash
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.ts`](../../../backend/src/db/seedHns.ts) 의 `firstToken()` 헬퍼로 첫 토큰만 검색 컬럼에 저장하고 원본 전체는 `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)으로 보강