"""검색 어댑터 공용 순수 유틸(부작용 없음). 레퍼런스의 parse_price 를 정리 이식.""" import re _NUM = re.compile(r"[\d,]+") _WON = re.compile(r"([\d,]+)\s*원") # '원' 바로 앞 숫자(단위가격/퍼센트 오인 방지) _NUM3 = re.compile(r"([\d,]{3,})") # 3자리+ 숫자 토큰(가격 후보) _SHIP_FEE = re.compile(r"배송비\s*([\d,]+)\s*원") _LABELS = ("상품명", "브랜드명", "판매가", "할인가") # 오픈마켓 카드의 a11y 라벨 프리픽스 def parse_price(value) -> int | None: """'44,900원', 44900, '44.900' 등 다형 입력 → int. 실패 시 None.""" if value is None: return None if isinstance(value, (int, float)): return int(value) m = _NUM.search(str(value)) if not m: return None digits = m.group(0).replace(",", "") return int(digits) if digits.isdigit() else None def extract_price(text: str) -> int | None: """가격 노드 텍스트 → int. '원' 앵커 우선, 없으면 첫 3자리+ 숫자. ('1%할인가44,540원' → 44540, '44,540' → 44540). 실패 시 None.""" if not text: return None m = _WON.search(text) if m: return int(m.group(1).replace(",", "")) m = _NUM3.search(text) return int(m.group(1).replace(",", "")) if m else None def clean_name(text: str) -> str: """오픈마켓 카드 이름에서 a11y 라벨('상품명'/'브랜드명' 등) 프리픽스를 제거.""" s = (text or "").strip() for lab in _LABELS: s = s.replace(lab, " ") return re.sub(r"\s+", " ", s).strip() def shipping_from_text(text: str, name: str | None = None) -> tuple[int | None, str | None]: """카드 텍스트에서 (배송비, 배송유형) 추출 — 오픈마켓 공용(로켓 없음). '무료배송'→(0,'free'), '배송비 X원'→(X,'paid'), 그 외 (None, None). 상품명에 '무료배송'이 들어간 오탐 방지를 위해 이름 제거 후 매칭.""" t = text or "" if name: t = t.replace(name, " ") if "무료배송" in t: return 0, "free" m = _SHIP_FEE.search(t) if m: return int(m.group(1).replace(",", "")), "paid" return None, None