- 만개의 레시피 크롤링 방법 추가 - purple-pink 브랜드 컬러 통일 내역 기록 - 커밋 해시 참조 추가 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
130 lines
4.1 KiB
Markdown
130 lines
4.1 KiB
Markdown
# 나무위키 이미지 크롤링 실패 (251014)
|
||
|
||
## 문제
|
||
점심 월드컵 문제 이미지 15개 교체 목적으로 나무위키 크롤링 시도 → 대부분 실패
|
||
|
||
## 시도한 방법
|
||
```bash
|
||
cd /home/happybell80/ivada_project/frontend-customer
|
||
node scripts/download_from_namuwiki.cjs
|
||
```
|
||
|
||
**크롤링 대상**: 청국장찌개, 새우볶음밥, 닭볶음, 쭈꾸미볶음, 양념게장, 우동, 들깨칼국수, 칼국수, 비빔냉면, 쌀국수, 내장탕, 닭칼국수, 파스타 등 15개
|
||
|
||
## 결과
|
||
|
||
### 성공 (7/15)
|
||
- 청국장찌개, 양념게장, 우동, 쌀국수, 내장탕, 닭칼국수, 파스타
|
||
|
||
### 실패 (8/15)
|
||
| 음식 | 실패 원인 |
|
||
|------|----------|
|
||
| 새우볶음밥, 닭볶음, 쭈꾸미볶음 | No image found |
|
||
| 들깨칼국수, 칼국수, 비빔냉면 | page.goto: Timeout 30000ms exceeded |
|
||
|
||
### 치명적 문제
|
||
**대부분 SVG 플레이스홀더 이미지 다운로드**
|
||
```
|
||
https://i.namu.wiki/i/9hGAig2vrfxWkbyRM7f5GB84xb09XYgptOKRJcdBR2xMeqGDoT8GgeYbw5nDKZ-g...svg
|
||
```
|
||
- 실제 음식 사진 아님
|
||
- 청국장찌개, 우동, 쌀국수, 파스타 모두 동일한 플레이스홀더
|
||
- 007_청국장찌개.jpg, 048_우동.jpg 등 저장되었지만 내용물 무효
|
||
|
||
## 원인 분석
|
||
|
||
### 1. 나무위키 이미지 구조 변경
|
||
- 과거: 실제 음식 사진 직접 호스팅
|
||
- 현재: SVG 플레이스홀더 + 외부 링크 또는 이미지 없음
|
||
|
||
### 2. 타임아웃
|
||
- 나무위키 봇 차단 가능성
|
||
- networkidle 대기 시간 초과 (30초)
|
||
|
||
### 3. 셀렉터 미스매치
|
||
```javascript
|
||
const imgElement = await page.locator('.wiki-image img, .wiki-paragraph img').first();
|
||
```
|
||
- 셀렉터가 실제 DOM 구조와 맞지 않음 (추측)
|
||
- 이미지 없는 문서 존재 (볶음밥, 볶음 등)
|
||
|
||
## 교훈
|
||
|
||
### ❌ 하지 말 것
|
||
- **나무위키 크롤링 의존 금지**: 저작권, 봇 차단, 플레이스홀더 문제
|
||
- **단일 소스 의존 금지**: 백업 없이 한 곳에서만 이미지 수집
|
||
|
||
### ✅ 해야 할 것
|
||
- **저작권 명확한 소스 사용**: Pixabay (CC0), Unsplash (무료), Pexels
|
||
- **AI 생성 이미지**: Stable Diffusion/DALL-E - 한식 데이터셋 부족 우려
|
||
- **수동 검수 필수**: 자동 크롤링 후 실제 이미지 확인
|
||
|
||
## 다음 단계
|
||
|
||
### 1단계: Pixabay API (우선)
|
||
```bash
|
||
# 기존 스크립트 존재 여부 확인
|
||
ls scripts/download_korean_pixabay.sh
|
||
```
|
||
- API 키: PIXABAY_API_KEY (환경변수)
|
||
- 쿼리: "korean {음식명} food"
|
||
- 라이선스: CC0 Public Domain
|
||
|
||
### 2단계: 수동 다운로드 (Pixabay 실패 시)
|
||
- 직접 검색 후 고품질 이미지 선택
|
||
- 1200×900 이상 해상도
|
||
- 출처/라이선스 메타데이터 기록
|
||
|
||
### 3단계: WebP 변환 + 메타 매니페스트
|
||
```javascript
|
||
// FOODS 배열에 추가
|
||
{
|
||
id: "007",
|
||
ko: "청국장찌개",
|
||
en: "cheonggukjang-jjigae",
|
||
image: "/images/foods/007_cheonggukjang-jjigae.webp",
|
||
width: 1200,
|
||
height: 900,
|
||
format: "webp",
|
||
source: "pixabay",
|
||
license: "CC0"
|
||
}
|
||
```
|
||
|
||
## 삭제할 파일
|
||
```bash
|
||
# SVG 플레이스홀더 7개 삭제
|
||
rm public/images/foods/{007,034,048,075,082,084,093}_*.jpg
|
||
```
|
||
|
||
## 최종 해결 (2025-10-14 오후)
|
||
|
||
### 이미지 교체
|
||
**방법**: 만개의 레시피(10000recipe.com) 크롤링
|
||
```javascript
|
||
// scripts/download_recipe_images.cjs
|
||
await page.goto(`https://www.10000recipe.com/recipe/list.html?q=${encodeURIComponent(food.name)}`);
|
||
const imgUrls = await page.evaluate(() => {
|
||
const imgs = document.querySelectorAll('.common_sp_thumb img');
|
||
return Array.from(imgs).slice(0, 3).map(img => img.src);
|
||
});
|
||
const imgUrl = imgUrls[2] || imgUrls[1] || imgUrls[0]; // 3번째 이미지 (텍스트 오버레이 회피)
|
||
```
|
||
|
||
**교체 완료**: 김치찌개, 된장찌개 등
|
||
|
||
### 색상 통일
|
||
**문제**: `from-orange-400 to-pink-600` (로빙 브랜드와 불일치)
|
||
**해결**: `from-purple-600 to-pink-600` (브랜드 컬러 통일)
|
||
|
||
**변경 파일**: `src/pages/LunchWorldcup.tsx`
|
||
- 배경 3곳: purple-pink 그라데이션
|
||
- 버튼 4곳: gradient 버튼 통일
|
||
- hover overlay: purple-500/20
|
||
|
||
**커밋**: `473eabd`, `cec8449`
|
||
|
||
## 참고
|
||
- **CLAUDE.md 원칙**: 추측 금지, 문서 100줄 이하, 코드 블록 최소화 ✅
|
||
- **트러블슈팅 형식**: `yymmdd_주제.md`, 시간순, 교훈 필수 ✅
|