"""11번가 검색 어댑터 — 네이버 폴백용(네이버에 11번가가 없을 때만 크롤). 공식 오픈API 는 판매자 계정 필요라 불가 → PC 웹(search.11st.co.kr) 크롤. 챌린지 없이 렌더되므로 ready_selector(카드) 대기만으로 충분하다. """ from urllib.parse import quote from services.search.browser_base import BrowserSearchAdapter from services.search.contract import NormalizedProduct from services.search.card_parser import parse_cards from services.search.st11.selectors import SEARCH_URL, READY_SELECTOR, CARDS _BLOCK_MARKERS = ("captcha", "robot", "비정상적인 접근", "errors.edgesuite.net") class ElevenStAdapter(BrowserSearchAdapter): source = "st11" block_markers = _BLOCK_MARKERS min_result_html = 20000 # PC 정상 결과는 수백 KB — 차단/미렌더 페이지는 작다(→회전/재시도) ready_selector = READY_SELECTOR ready_timeout_ms = 20000 block_resources_default = True # 라우팅 on — 이미지/미디어/폰트만(CSS/JS 유지해야 렌더됨) blocked_resource_types = {"image", "media", "font"} scroll_steps = 3 # 결과가 지연 로딩 → 스크롤로 트리거 def _search_url(self, query: str, limit: int) -> str: return SEARCH_URL.format(q=quote(query)) def _parse(self, html: str) -> list[NormalizedProduct]: return parse_cards(html, CARDS)