From b98d694b65505508706951aae8a5e2e1c3569480 Mon Sep 17 00:00:00 2001 From: JOUNGWOOK KWON Date: Mon, 30 Mar 2026 17:54:07 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EB=AA=A9=EC=B0=A8=20=EC=99=84=EC=A0=84?= =?UTF-8?q?=20=EC=A0=9C=EA=B1=B0,=20Wikipedia=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20fallback=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. publisher_bot.py + blog_converter.py: 목차(TOC) 완전 비활성화 2. fetch_featured_image(): Wikipedia REST API로 무료 이미지 fallback - 제목/태그로 한국어 Wikipedia 검색 → 썸네일 추출 - 실패 시 영문 Wikipedia 시도 (최대 4개 키워드) - 200px 썸네일 → 800px 고해상도로 교체 Co-Authored-By: Claude Sonnet 4.6 --- bots/converters/blog_converter.py | 3 +-- bots/publisher_bot.py | 41 ++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/bots/converters/blog_converter.py b/bots/converters/blog_converter.py index 0f73de9..a6a4e5a 100644 --- a/bots/converters/blog_converter.py +++ b/bots/converters/blog_converter.py @@ -96,8 +96,7 @@ def build_full_html(article: dict, body_html: str, toc_html: str, json_ld = build_json_ld(article, post_url) disclaimer = article.get('disclaimer', '') parts = [json_ld] - if toc_html: - parts.append(f'
{toc_html}
') + # 목차 비활성화 — 독자 경험 개선 parts.append(body_html) if disclaimer: parts.append(f'

{disclaimer}

') diff --git a/bots/publisher_bot.py b/bots/publisher_bot.py index 36dbfb7..52604af 100644 --- a/bots/publisher_bot.py +++ b/bots/publisher_bot.py @@ -299,6 +299,42 @@ def fetch_featured_image(article: dict) -> str: except Exception as e: logger.warning(f"Pexels 이미지 검색 실패: {e}") + # 4) Wikipedia 썸네일 (무료, API 키 불필요) + title = article.get('title', '') + tags = article.get('tags', []) + if isinstance(tags, str): + tags = [t.strip() for t in tags.split(',')] + for kw in ([title] + tags)[:4]: + if not kw: + continue + try: + from urllib.parse import quote + wiki_url = f'https://ko.wikipedia.org/api/rest_v1/page/summary/{quote(kw)}' + resp = requests.get(wiki_url, timeout=6, + headers={'User-Agent': 'Mozilla/5.0 (compatible; BlogBot/1.0)'}) + if resp.status_code == 200: + data = resp.json() + thumb = data.get('thumbnail', {}).get('source', '') + if thumb and thumb.startswith('http') and not _is_platform_logo(thumb): + # 더 큰 해상도로 변환 (200px → 800px) + thumb = thumb.replace('/200px-', '/800px-').replace('/320px-', '/800px-') + return thumb + except Exception: + pass + # 영문 Wikipedia fallback + try: + wiki_url = f'https://en.wikipedia.org/api/rest_v1/page/summary/{quote(kw)}' + resp = requests.get(wiki_url, timeout=6, + headers={'User-Agent': 'Mozilla/5.0 (compatible; BlogBot/1.0)'}) + if resp.status_code == 200: + data = resp.json() + thumb = data.get('thumbnail', {}).get('source', '') + if thumb and thumb.startswith('http') and not _is_platform_logo(thumb): + thumb = thumb.replace('/200px-', '/800px-').replace('/320px-', '/800px-') + return thumb + except Exception: + pass + return '' @@ -323,10 +359,7 @@ def build_full_html(article: dict, body_html: str, toc_html: str) -> str: ) html_parts.append(json_ld) - # 목차는 h2가 3개 이상일 때만 표시 (짧은 글에선 불필요) - h2_count = body_html.lower().count('= 3: - html_parts.append(f'
{toc_html}
') + # 목차 비활성화 — 독자 경험 개선 (사진 아래 목차 제거) html_parts.append(body_html) # 원문 출처 링크