feat(identity): weighted evidence table, sequel numbers, generic-name guard (ID-2)

Configurable DEFAULT_MATCH_WEIGHTS; Chinese/English names both count and
corroborate; Chapter/Part/第N章 sequel conflicts reject; missing season
penalised; category words and single-word aliases colliding in the pool
cannot confirm alone; alias-only hits need year or second-script support;
same-level ties broken by exact year then matched name scripts.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-29 17:41:22 +08:00
1 parent 51e0032d14
commit f6ec993b5f
5 files changed
+527 -34

No files matched your search

+66
View File
@@ -35,3 +35,69 @@ export function normalizeTitle(s: string): string {
.replace(/&/g, "and")
.replace(/[^\p{L}\p{N}]+/gu, "");
}
/** 分类词(站点分类 / RSS 标题前缀)与常见停用词:不能当片名或别名用于身份比对(ID-2) */
const GENERIC_NAMES = new Set(
[
"电影",
"电视剧",
"剧集",
"连续剧",
"动漫",
"动画",
"番剧",
"国漫",
"日漫",
"综艺",
"纪录片",
"记录片",
"音乐",
"短剧",
"微短剧",
"体育",
"游戏",
"软件",
"学习",
"其他",
"其它",
"未知",
"新",
"合集",
"全集",
"中字",
"国语",
"粤语",
"高清",
"蓝光",
"原盘",
"movie",
"movies",
"tv",
"tvseries",
"series",
"anime",
"animation",
"documentary",
"music",
"variety",
"show",
"the",
"season",
"complete",
"unknown",
"other",
].map((s) => s.toLowerCase()),
);
/**
* 归一化后的名称是否太"通用"不能用于身份比对:分类词、停用词、单个汉字、两个以内的拉丁字符、纯数字。
* 参数是 normalizeTitle 之后的形态。
*/
export function isGenericAliasName(norm: string): boolean {
if (!norm) return true;
if (GENERIC_NAMES.has(norm)) return true;
if (/^\d+$/.test(norm)) return true;
const han = norm.match(/\p{Script=Han}/gu)?.length ?? 0;
if (han > 0) return [...norm].length < 2;
return norm.length <= 2;
}