| .. | ||
| extract-excel.py | ||
| extract-images.py | ||
| extract-pdf.py | ||
| merge-batch.py | ||
| merge-data.ts | ||
| ocr-claude-vision.ts | ||
| ocr-local.py | ||
| README.md | ||
| requirements.txt | ||
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.ts 의 firstToken() 헬퍼로 첫 토큰만 검색 컬럼에 저장하고 원본 전체는 DATA JSONB에 보존.