fix(color_extractor): CSS .logo 패턴 우선순위 + lang/flag noise 필터 강화

문제: JK 성형외과 (jkplastic.com) 처럼 <h1 class="logo"><a>JK PLASTIC</a></h1>
형태로 logo 텍스트만 있고 진짜 이미지는 외부 CSS의 .logo { background-image: url(...) }
로 들어가는 사이트에서, generic <header> 첫 img 패턴이 한국어 깃발(lang-kor.png)을
먼저 잡아 잘못된 로고가 박혔음.

수정:
- find_logo_url_in_html 흐름 재정렬:
  1) class/id/alt/src 명시 + 부모 class="logo" + 중첩 img (specific)
  2) **외부 CSS 의 .logo background-image** ← generic 보다 앞으로 (class-based 라
     더 specific)
  3) <header>/<nav> 첫 img (가장 generic, 잘못 잡힐 위험)
- noise 필터 강화: lang-kor / lang-eng / flag / country / icon- / btn- / arrow /
  prev / next / search 같이 logo 아닌 게 명백한 src 는 모든 단계에서 skip

검증: JK 는 lang-kor.png → logo-color.png 로 정확히 잡힘.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
channel-brand
Mina Choi 2026-05-29 10:45:08 +09:00
parent dca0c78860
commit fa32109658
1 changed files with 32 additions and 7 deletions

View File

@ -84,22 +84,47 @@ LOGO_CSS_PATTERN = re.compile(
def find_logo_url_in_html(html: str, base_url: str, css_texts: list[str] | None = None) -> str | None: def find_logo_url_in_html(html: str, base_url: str, css_texts: list[str] | None = None) -> str | None:
"""HTML에서 logo URL 찾기. class/id/alt → 부모 + 중첩 img → background-image → src에 logo → header/nav → og:image 순.""" """HTML에서 logo URL 찾기. 우선순위:
for pat in LOGO_IMG_PATTERNS: 1) 패턴 1~8 (class/id/alt/src에 'logo' 명시된 img 가장 specific)
2) 외부 CSS의 .logo background-image (class-based, specific)
3) 패턴 9~10 (<header>/<nav> img 가장 generic, 잘못 잡힐 위험 )
"""
def _is_noise(src: str) -> bool:
"""logo로 잘못 잡힐 가능성 높은 URL 패턴 — lang/flag/icon/arrow/spacer 등."""
if not src or src.startswith("data:"):
return True
if re.search(r"(blank|spacer|pixel|transparent|1x1)\b", src, re.IGNORECASE):
return True
# 헤더 첫 img가 lang flag / 검색 아이콘 / 네비 화살표인 경우 (JK plastic 한국어 깃발이 잡히던 케이스)
if re.search(r"(lang[-_]?(kor|eng|chn|jpn|rus|jp|en|ko|cn|ar|in)|flag|country|icon-|btn-|arrow|prev|next|search)\b", src, re.IGNORECASE):
return True
return False
# 1) class/id/alt/src/inline-bg/src-with-logo 패턴 (1~8)
for pat in LOGO_IMG_PATTERNS[:8]:
for m in pat.finditer(html): for m in pat.finditer(html):
src = m.group(1) src = m.group(1)
if not src or src.startswith("data:"): if _is_noise(src):
continue
if re.search(r"(blank|spacer|pixel|transparent|1x1)\b", src, re.IGNORECASE):
continue continue
return urljoin(base_url, src) return urljoin(base_url, src)
# 외부 CSS에서 .logo background-image 추출
# 2) 외부 CSS의 .logo { background-image } — class-based 이므로 generic 패턴보다 우선
for css in (css_texts or []): for css in (css_texts or []):
m = LOGO_CSS_PATTERN.search(css) m = LOGO_CSS_PATTERN.search(css)
if m: if m:
src = m.group(1) src = m.group(1)
if src and not src.startswith("data:"): if not _is_noise(src):
return urljoin(base_url, src) return urljoin(base_url, src)
# 3) header/nav 첫 img — 가장 generic, lang flag 등 noise 필터 강화 적용
for pat in LOGO_IMG_PATTERNS[8:]:
for m in pat.finditer(html):
src = m.group(1)
if _is_noise(src):
continue
return urljoin(base_url, src)
return None return None