141 lines
4.9 KiB
Markdown
141 lines
4.9 KiB
Markdown
# 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에 보존.
|