Summary
SourceAdapter 인터페이스에 WhatsOnTheStarAdapter(platform=whatsonthestar)를 추가한다. Pinterest/Instagram과 달리 이 소스는 이미 셀럽-아이템(브랜드/상품명/가격)이 구조화 라벨링된 데이터라서, vision auto-tag를 우회하거나 ground-truth로 활용할 수 있다.
cf. #214 PinterestAdapter / #259 InstagramAdapter — 같은 패턴으로 등록.
사이트 분석
- URL: https://whatsonthestar.com
- 타입: 셀럽 outfit 식별 + 쇼핑 링크 (Lil Yachty, Lil Baby 등 힙합/연예인 중심)
- 렌더링: Nuxt.js SSR — 모든 페이지에 `window.NUXT=(function(...){...})` 형태로 데이터 임베드
- 공식 API: 프론트엔드용 공개 엔드포인트는 노출되지 않음 (`api.whatsonthestar.com`/`/api/*` 모두 404). iOS 앱(id=1534214433) 전용 API는 별도 분석 필요
- robots.txt: `Disallow: //go/` 만 — affiliate redirect 경로만 차단, 콘텐츠 크롤 허용
- sitemap: `https://cdn.whatsonthestar.com/sitemaps/sitemap.xml\` (lastmod 2020 — 거의 갱신 안 됨, 페이지 인벤토리 부정확)
데이터 구조 (포스트 단위)
각 outfit 포스트에 다음 필드:
- celebrity: 이름 + 프로필 slug
- date worn: 착용 날짜
- outfit total: 전체 합계
- items[]: `{brand, product_title, price, sale_price, retailer_url(affiliate)}`
- photo URL
스크랩 전략 (제안)
- 1순위: `window.NUXT` 페이로드 파싱 — Nuxt가 SSR로 직렬화해주는 JSON에서 outfit/items 추출. 헤드리스 없이 가능 (regex/AST로 추출 후 `eval(function(...))` 평가). `api-server`의 기존 `httpx` + `pyminify` 또는 `mini-racer` 한정 평가
- fallback: BeautifulSoup으로 outfit 카드 / item 리스트 DOM 파싱
- discovery:
- 셀럽 인덱스(`/celebrities/`) → 셀럽 별 페이지(`/celebrities/{slug}`) → outfit 페이지
- 또는 `/recent` / `/popular` 류 글로벌 피드(확인 필요)
- rate limit: 1 req/sec 보수적, exponential backoff
RawMedia 매핑
```python
RawMedia(
external_id=outfit_id, # 사이트 내부 ID
external_url="https://whatsonthestar.com/outfits/{slug}",
image_url=outfit_photo_url,
caption=f"{celebrity} on {date_worn}",
author_name=celebrity_name,
platform_metadata={
"celebrity_slug": ...,
"date_worn": ...,
"outfit_total": ...,
"items": [
{"brand": ..., "title": ..., "price": ..., "sale_price": ..., "retailer_url": ...}
],
},
)
```
Ground-truth 활용 (#348 processor 연계)
기존 vision pipeline은 사진에서 아이템을 detect하지만, 이 소스는 이미 라벨이 있다. 옵션:
- A. 우회: `parse_status='parsed'`로 직접 INSERT, `parse_result`에 라벨 그대로 저장
- B. 검증용: vision 돌리고 사이트 라벨과 비교 → recall/precision 측정 데이터로 활용
- C. 하이브리드: bbox는 vision, brand/title은 site 라벨
Phase 1은 A 권장. B는 별도 evaluation 잡으로 분리.
Scope (this issue)
Out of scope
Acceptance
- 셀럽 페이지 1개로 `fetch()` → `List[RawMedia]` 반환 (≥10 items 페이지에서)
- 아이템 메타(brand/title/price)가 `platform_metadata.items`에 보존
- 테스트 그린, lint 통과
Summary
SourceAdapter인터페이스에 WhatsOnTheStarAdapter(platform=whatsonthestar)를 추가한다. Pinterest/Instagram과 달리 이 소스는 이미 셀럽-아이템(브랜드/상품명/가격)이 구조화 라벨링된 데이터라서, vision auto-tag를 우회하거나 ground-truth로 활용할 수 있다.cf. #214 PinterestAdapter / #259 InstagramAdapter — 같은 패턴으로 등록.
사이트 분석
데이터 구조 (포스트 단위)
각 outfit 포스트에 다음 필드:
스크랩 전략 (제안)
RawMedia 매핑
```python
RawMedia(
external_id=outfit_id, # 사이트 내부 ID
external_url="https://whatsonthestar.com/outfits/{slug}",
image_url=outfit_photo_url,
caption=f"{celebrity} on {date_worn}",
author_name=celebrity_name,
platform_metadata={
"celebrity_slug": ...,
"date_worn": ...,
"outfit_total": ...,
"items": [
{"brand": ..., "title": ..., "price": ..., "sale_price": ..., "retailer_url": ...}
],
},
)
```
Ground-truth 활용 (#348 processor 연계)
기존 vision pipeline은 사진에서 아이템을 detect하지만, 이 소스는 이미 라벨이 있다. 옵션:
Phase 1은 A 권장. B는 별도 evaluation 잡으로 분리.
Scope (this issue)
Out of scope
Acceptance