feat(classify): zero title-only titles, penalize <10min, add discover.candidate_min_score

标题仅含 require_title 不再计分(必须咻咻满+任一正向词);时长 <10 分钟 -1(时长未知不扣);新增 discover.candidate_min_score(默认=notify.min_score)控制是否进候选池,只过标题关的不再入池。库内 796 条:仅过标题关的 8 条从 1/3 分降为 0/-1,其余不变。
This commit is contained in:
kairee committed 2026-11-01 20:18:43 +08:00
1 parent aa9aa7c589
commit c6790f0ba1
10 files changed
+138 -69

No files matched your search

+28 -4
View File
@@ -35,6 +35,7 @@ def write_config(tmp, **discover):
"keywords": ["咻咻满 reaction"],
"pages": 1,
"window_days": 14,
"candidate_min_score": 0,
**discover,
},
"classify": {
@@ -91,8 +92,8 @@ def item(aid, *, title="咻咻满 reaction", up_mid=100, pubdate=NOW - 3600,
)
def make_service(tmp, items, *, notifier=None):
path = write_config(tmp)
def make_service(tmp, items, *, notifier=None, **discover):
path = write_config(tmp, **discover)
store = ConfigStore(path, env={})
db = Database(Path(tmp) / "app.db", backup_dir=Path(tmp) / "backup")
db.initialize()
@@ -128,9 +129,9 @@ def test_filters_and_scoring():
assert summary.title_miss == 1
assert summary.old == 1
assert summary.blacklisted == 1
assert summary.candidates == 2 # aid 6(1 分)与 aid 2(2 分)
assert summary.candidates == 2 # aid 6(0 分)与 aid 2(2 分)
assert summary.notified == 0
assert repo.get_candidate(6)["score"] == 1
assert repo.get_candidate(6)["score"] == 0 # 只过标题关:0 分
assert repo.get_candidate(2)["score"] == 2 # reaction 命中后单个「切片」不再清零
assert repo.get_candidate(4) is None
assert repo.get_candidate(5) is None
@@ -217,12 +218,35 @@ def test_duplicate_search_results_notified_once():
db.close()
def test_candidate_min_score_floor():
with tempfile.TemporaryDirectory() as tmp:
db, repo, service = make_service(
tmp,
[
item(1, title="咻咻满 reaction 充电"), # 9 分 -> 入池
item(2, title="咻咻满 日常"), # 0 分 -> 只过标题关,不入池
item(3, title="咻咻满 reaction 切片"), # 2 分 -> 低于候选线,不入池
],
candidate_min_score=4,
)
try:
summary = service.run()
assert summary.scored == 3
assert summary.candidates == 1
assert repo.get_candidate(1) is not None
assert repo.get_candidate(2) is None
assert repo.get_candidate(3) is None
finally:
db.close()
def main():
test_filters_and_scoring()
test_notification_batch_and_failure()
test_search_error_does_not_abort_other_keywords()
test_pending_candidate_notified_on_later_run()
test_duplicate_search_results_notified_once()
test_candidate_min_score_floor()
print("OK: 发现过滤、打分、候选池与通知批次测试全部通过")