네이버 폴백용 오픈마켓 크롤러 3종. 4중 복제를 피해 BrowserSearchAdapter 베이스로 브라우저 수명·프록시 회전·차단감지+IP회전 재시도·감지기록을 공유하고, 사이트 차이는 훅(_search_url/_parse/ready_selector/block_markers)으로 분리. - browser_base: patchright 공통 machinery(쿠팡 machinery 일반화) - card_parser: 오픈마켓 공용 카드 파서(CardConfig 주입) + util(extract_price/clean_name/shipping) - esm: G마켓·옥션(eBay 백엔드 공유, site 파라미터 1개로 커버, '잠시만' 챌린지 대기) - st11: 11번가 PC(공식API 판매자계정 필요라 불가). 지연로딩 → scroll_steps, '.c-card-item' 토큰 - 학습 반영: 오픈마켓은 리소스차단 OFF(렌더/챌린지 깨짐), 스턱 챌린지='잠시만' 잔존 시 차단 간주→IP회전 - 파서 결정론 테스트 7종(실렌더 카드 3개씩 경량 fixture). 라이브 검증: 신선 IP로 3사 모두 파싱 성공 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
31 lines
1.3 KiB
Python
31 lines
1.3 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 = 20000
|
|
block_resources_default = False # 리소스 차단 시 goto 가 hang / 렌더 실패
|
|
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)
|