feat(recency): Frische-Suchfeed (when:14d) + Aktualitaets-Score
Damit die Pipeline das aktuelle Bild einfaengt, nicht nur das relevanteste (oft Monate alt). Bei der Test-Lage Qilin war der neueste Artikel 7 Wochen alt, die Masse 6-7 Monate — weil Google-News-Volltextsuche nach Relevanz rankt, nicht nach Datum. - build_news_search_feeds: neuer Parameter recency_days. Wenn gesetzt, wird der Google-News-Operator "when:Nd" an die Query gehaengt — der Feed liefert nur Artikel der letzten N Tage. Eigene Domain-Gruppe '...-recent'. - orchestrator._rss_pipeline: baut jetzt ZWEI Suchfeed-Saetze — einen Kontext-Feed (alle Zeiten) und einen Frische-Feed (when:14d). Beide laufen durch dieselbe Pipeline, Dedup entfernt Ueberschneidungen. - rss_parser._fetch_feed: relevance_score bekommt einen Aktualitaets-Bonus (<=3d +0.35, <=14d +0.20, <=60d +0.05) bzw. -Malus (>180d -0.15, >365d -0.30). Damit ueberleben frische Artikel den Domain-Cap statt von alten verdraengt zu werden. Nur adhoc-Pfad betroffen — research-Lagen ueberspringen die RSS-Pipeline ohnehin und behalten ihre volle historische Tiefe. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -218,14 +218,33 @@ class RSSParser:
|
||||
|
||||
if match_count >= min_matches:
|
||||
published = None
|
||||
published_dt = None
|
||||
if hasattr(entry, "published_parsed") and entry.published_parsed:
|
||||
try:
|
||||
published = datetime(*entry.published_parsed[:6], tzinfo=timezone.utc).astimezone(TIMEZONE).isoformat()
|
||||
published_dt = datetime(*entry.published_parsed[:6], tzinfo=timezone.utc)
|
||||
published = published_dt.astimezone(TIMEZONE).isoformat()
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
|
||||
# Relevanz-Score: Anteil der gematchten Suchworte (0.0-1.0)
|
||||
relevance_score = match_count / len(search_words) if search_words else 0.0
|
||||
# Aktualitaets-Bonus/Malus: frische Artikel sollen den
|
||||
# Domain-Cap (sortiert nach relevance_score) ueberleben und
|
||||
# nicht von Monate alten verdraengt werden. Damit faengt die
|
||||
# Pipeline das aktuelle Bild ein. Nur adhoc-Pfad — research
|
||||
# nutzt diesen Code nicht.
|
||||
if published_dt is not None:
|
||||
age_days = (datetime.now(timezone.utc) - published_dt).days
|
||||
if age_days <= 3:
|
||||
relevance_score += 0.35
|
||||
elif age_days <= 14:
|
||||
relevance_score += 0.20
|
||||
elif age_days <= 60:
|
||||
relevance_score += 0.05
|
||||
elif age_days > 365:
|
||||
relevance_score -= 0.30
|
||||
elif age_days > 180:
|
||||
relevance_score -= 0.15
|
||||
|
||||
# Bei Google-News-Feeds: echten Publisher aus <source>-Tag holen
|
||||
article_source = name
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren