v1.5.3: filter vereist titel-match of totaalscore >= 3
Regel C: doorlaten bij (titel-match >= 1) of (totaalscore >= 3). Een treffer in de titel is een sterke OV-intentie (score 2 volstaat); treffers alleen in de samenvatting moeten dubbel bevestigd worden. Weert bv. woningbrand-berichten die via 'bussen rijden om'/'busverkeer' in de lead binnenkwamen, zonder de 112/trein/staking-berichten te raken. Gevalideerd op 30d kamerhistorie: 96 doorlaat -> 7 geblokkeerd (allemaal ruis).
This commit is contained in:
parent
aa4f7144be
commit
cb6d00e707
2 changed files with 33 additions and 18 deletions
|
|
@ -158,23 +158,38 @@ class RSSBot(Plugin):
|
||||||
except Exception:
|
except Exception:
|
||||||
self.log.exception("Fatal error while polling feeds")
|
self.log.exception("Fatal error while polling feeds")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _matches_in(text: str, match_filter: str) -> int:
|
||||||
|
"""Aantal aaneengesloten match-clusters in text (0 als geen match).
|
||||||
|
Aaneengesloten matches (bv 'NS-trein', 'openbaar vervoer') tellen als 1."""
|
||||||
|
spans = sorted((m.start(), m.end()) for m in re.finditer(match_filter, text))
|
||||||
|
if not spans:
|
||||||
|
return 0
|
||||||
|
clusters, prev_end = 1, spans[0][1]
|
||||||
|
for s, e in spans[1:]:
|
||||||
|
if s - prev_end <= 1:
|
||||||
|
prev_end = max(prev_end, e)
|
||||||
|
else:
|
||||||
|
clusters += 1
|
||||||
|
prev_end = e
|
||||||
|
return clusters
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _filter_score(title: str, summary: str, match_filter: str) -> int:
|
def _filter_score(title: str, summary: str, match_filter: str) -> int:
|
||||||
"""Score = 2× hits in titel + 1× hits in summary. Aaneengesloten matches
|
"""Score = 2× hits in titel + 1× hits in summary."""
|
||||||
(bv 'NS-trein', 'openbaar vervoer') tellen als 1 cluster."""
|
return 2 * RSSBot._matches_in(title, match_filter) + RSSBot._matches_in(summary, match_filter)
|
||||||
def count(text: str) -> int:
|
|
||||||
spans = sorted((m.start(), m.end()) for m in re.finditer(match_filter, text))
|
@staticmethod
|
||||||
if not spans:
|
def _filter_passes(title: str, summary: str, match_filter: str) -> bool:
|
||||||
return 0
|
"""Regel C: doorlaten bij (titel-match >= 1) of (totaalscore >= 3).
|
||||||
clusters, prev_end = 1, spans[0][1]
|
|
||||||
for s, e in spans[1:]:
|
Een OV-trefwoord in de titel is een sterke intentieverklaring (score 2
|
||||||
if s - prev_end <= 1:
|
volstaat). Treffers alleen in de samenvatting moeten dubbel bevestigd
|
||||||
prev_end = max(prev_end, e)
|
worden (>= 3): zo houdt 'bussen rijden om' in de lead van een
|
||||||
else:
|
woningbrand-bericht het artikel niet meer binnen."""
|
||||||
clusters += 1
|
if RSSBot._matches_in(title, match_filter) >= 1:
|
||||||
prev_end = e
|
return True
|
||||||
return clusters
|
return RSSBot._filter_score(title, summary, match_filter) >= 3
|
||||||
return 2 * count(title) + count(summary)
|
|
||||||
|
|
||||||
async def _send(
|
async def _send(
|
||||||
self, feed: Feed, entry: Entry, sub: Subscription, *, check_filter: bool = True
|
self, feed: Feed, entry: Entry, sub: Subscription, *, check_filter: bool = True
|
||||||
|
|
@ -183,7 +198,7 @@ class RSSBot(Plugin):
|
||||||
match_filter = self.config["match_filter"]
|
match_filter = self.config["match_filter"]
|
||||||
if match_filter:
|
if match_filter:
|
||||||
summary = html.unescape(re.sub(r"<[^>]+>", "", entry.summary))
|
summary = html.unescape(re.sub(r"<[^>]+>", "", entry.summary))
|
||||||
if self._filter_score(entry.title, summary, match_filter) < 2:
|
if not self._filter_passes(entry.title, summary, match_filter):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
message = sub.notification_template.safe_substitute(
|
message = sub.notification_template.safe_substitute(
|
||||||
|
|
@ -217,7 +232,7 @@ class RSSBot(Plugin):
|
||||||
match_filter = self.config["match_filter"]
|
match_filter = self.config["match_filter"]
|
||||||
if match_filter:
|
if match_filter:
|
||||||
summary = html.unescape(re.sub(r"<[^>]+>", "", entry.summary))
|
summary = html.unescape(re.sub(r"<[^>]+>", "", entry.summary))
|
||||||
if self._filter_score(entry.title, summary, match_filter) < 2:
|
if not self._filter_passes(entry.title, summary, match_filter):
|
||||||
return 0, 1, 0
|
return 0, 1, 0
|
||||||
spam_sleep = self.config["spam_sleep"]
|
spam_sleep = self.config["spam_sleep"]
|
||||||
if spam_sleep >= 0:
|
if spam_sleep >= 0:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
id: nl.eddydevink.rss
|
id: nl.eddydevink.rss
|
||||||
version: 1.5.2
|
version: 1.5.3
|
||||||
modules:
|
modules:
|
||||||
- buzzrss
|
- buzzrss
|
||||||
main_class: RSSBot
|
main_class: RSSBot
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue