G마켓 챌린지가 안 풀린 채 25~70초를 먹던 문제에 상한을 씌운다. 폴백은 '있으면 좋은' 보강이라 데드라인으로 잘라도 안전(그 몰만 스킵). - handler: 각 폴백 크롤에 fallback_deadline_sec(기본 15s) wait_for. 초과 시 스킵. _timed_search 예외를 BaseException 로(CancelledError 계측 포함). - 폴백 어댑터 max_block_retries=0(챌린지 대기 2배 방지), ESM ready_timeout 22→12s, st11 20→15s. - 테스트: 느린 폴백 데드라인 스킵 1종. 실측(동시성2·4상품): 상품당 p50 84.6s→34.2s(~2.5x), 벽시계 181s→65s(~2.8x), 처리량 1.3→3.7 상품/분, 1000건 $7.12→$5.06(~29%↓, 실패 챌린지 대역폭 절감). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
32 lines
1.4 KiB
Python
32 lines
1.4 KiB
Python
"""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 = 15000
|
|
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)
|