This commit is contained in:
lychang
2026-07-20 04:07:40 +08:00
parent 9093f08441
commit 00af6e8528
4 changed files with 354 additions and 5 deletions

View File

@@ -346,6 +346,7 @@
"color_bg": "#f0fdfa",
"color_fg": "#0f766e",
"words": [
"香格里拉",
"苏梅岛",
"日本",
"韩国",
@@ -520,6 +521,9 @@
}
},
"stop_words": [
"写真",
"性感",
"美女",
"photos",
"photo",
"pictures",
@@ -688,7 +692,325 @@
"张馨予",
"程开心",
"赵小米",
"小齿优喵"
"小齿优喵",
"周于希",
"王雨纯",
"绮里嘉",
"唐安琪",
"筱慧",
"冯木木",
"许诺",
"言沫",
"丽莎",
"易阳",
"陈良玲",
"蓝夏",
"凯竹",
"郑颖姗",
"刘飞儿",
"于姬",
"玉兔",
"穆菲菲",
"夏沫沫",
"雪晴",
"熊吖",
"小夕",
"谢芷馨",
"顾奈奈",
"唐琪儿",
"熊小诺",
"黄歆苑",
"艾小青",
"李雅",
"晓茜",
"李宓儿",
"林乐",
"雪千寻",
"艾静香",
"阿薰",
"李承美",
"葛征",
"沈佳熹",
"陈思琪",
"刘娅",
"小瑶",
"张思允",
"李梓",
"宝儿",
"程小烦",
"馬吉",
"叶佳",
"冯雪娇",
"栗子",
"丁筱南",
"小仓",
"小玉",
"何嘉颖",
"皮卡丘",
"小娜",
"李李",
"安妮",
"艾栗栗",
"李雅柔",
"静安",
"利世",
"云溪溪",
"白莉",
"小青茗",
"战姝羽",
"若兮",
"韩恩熙",
"娜露",
"周大萌",
"刘艾琳",
"王婉悠",
"李猩",
"西儿",
"木之本",
"瓜希",
"嘉嘉",
"阳光",
"琳琳",
"娜比",
"梁莹",
"李雪婷",
"栗栗栗",
"斯朵拉",
"吴雪瑶",
"小欣奈",
"鹿初",
"阿依",
"努尔",
"瓦娅",
"白茹雪",
"顾乔楠",
"玄子",
"艾莉",
"绮梦",
"陈宇曦",
"王乔恩",
"雪峰",
"夏瑶",
"秋和柯",
"莫子",
"六味帝皇酱",
"娜娜",
"白领",
"桂林",
"周井空",
"伊莉娜",
"李妍",
"思淇",
"杨漫妮",
"陈雅漫",
"梓诺",
"秋雨",
"芊芊",
"伊小七",
"赵芸",
"蔡文钰",
"张静燕",
"白露",
"欧派",
"小沫琳",
"菲菲",
"徐妍馨",
"安琪",
"文芮",
"珊珊",
"延智恩",
"苏梅",
"苏雨",
"唐雨辰",
"乔漫妮",
"陈天扬",
"周思乔",
"允儿",
"香艳",
"程彤",
"卓芷伊",
"苏可",
"王雨",
"周妍",
"楊衣",
"封疆",
"阿雪雪",
"小九",
"朴正允",
"朱若慕",
"施忆佳",
"陈欣",
"大晗",
"夏诗雯",
"白衬衣",
"子纯儿",
"容颜",
"陈嘉嘉",
"艾小",
"奥莉",
"艾比",
"张优",
"赵伊",
"谭小灵",
"若姬子",
"乔依琳",
"慕羽茜",
"王语纯",
"吉普",
"白兔",
"陈一涵",
"瑞莎",
"闫盼盼",
"赵惟依",
"杨柳",
"小猫咪",
"孙允珠",
"张齐郡",
"唐思琪",
"朱赢",
"小潘鼠",
"顾灿",
"费若拉",
"白一晗",
"李薇薇",
"张雅筑",
"雪瑞",
"高开",
"白桃",
"陈舒羽",
"周熙",
"黄可",
"小琳",
"梦小楠",
"紫藤",
"余馨妍",
"米妮",
"西希",
"之恋",
"乐儿",
"石心琪",
"余心曼",
"蓝白",
"夏西",
"卿卿",
"小秘书",
"黑与白",
"杨晓",
"李玲",
"刘美辰",
"薄荷叶",
"乔雪",
"孔雀",
"唐婉儿",
"徐珍儿",
"何梦兮",
"瑞宝儿",
"夏诗诗",
"韩子",
"夏倪",
"谢小蒽",
"白銀",
"莱可",
"星萌",
"森森",
"白烨",
"熊仔",
"鹿野",
"艾西",
"内衣秀",
"林静瑶",
"崔灿",
"李师师",
"宋黛",
"花桃桃",
"谭晓彤",
"沈善熙",
"陳雅漫",
"红顾灿",
"心妍",
"温心怡",
"张美荧",
"李夫人",
"李筱乔",
"宝宝",
"王紫琳",
"贾诗晗",
"王梓",
"岑雨桥",
"于大乔",
"小雅",
"朴秀妍",
"楚恬",
"林煊煊",
"水嫩",
"古韵",
"苏小曼",
"于思琪",
"邓雪",
"智秀",
"大萌萌",
"林佳沫",
"小奈樱",
"阮阮",
"南歌",
"林幼",
"晓晓可",
"小琪",
"轩萧",
"小七",
"夏树",
"雪琪",
"筱田甜",
"曲奇",
"黄婧",
"陈雨涵",
"韩秀冉",
"王曼妮",
"丛林",
"小熊猫",
"韩好甜",
"曾水",
"王慧慧",
"孔雀蓝",
"雨纯",
"周小然",
"宛恩",
"陈宝拉",
"毛绒",
"李小星",
"高尔夫",
"小雨",
"木木",
"夏希子",
"童千艺",
"小可爱",
"琳娜",
"小萝莉",
"戴小唯",
"墨绿",
"白领丽人",
"程慧",
"刘艺蕾",
"巨无霸",
"安吉",
"浅紫色",
"唐心",
"吕婉柔",
"柴婉艺",
"金允乔",
"荣耀",
"李秀彬",
"迈阿密",
"赵智妍",
"花娇",
"廖挺",
"姜贞语",
"趙芸",
"夏可馨",
"雷丝",
"陈圆圆",
"赵梦洁",
"斯戴媛"
]
}
}

View File

@@ -357,8 +357,14 @@ pub async fn phase_parse_dirty(db: &Database, dirty_set: &DirtySet) -> (usize, u
let mut pending_tx: Option<sqlx::Transaction<'_, sqlx::Sqlite>> = None;
if let Some(name) = &best_person {
let (primary, aliases) = title_parser::split_person_name_with_aliases(name);
let final_name = if primary.is_empty() { name.clone() } else { primary };
// 尝试用 include 列表扩展为更长的完整匹配(如 "杨晨晨" → "杨晨晨Yome")
let expanded = tag_dict::get_tag_dict()
.find_longest_included_match(name)
.filter(|longer| longer.len() > name.len()); // 仅当更长时替换
let effective_name = expanded.as_deref().unwrap_or(name.as_str());
let (primary, aliases) = title_parser::split_person_name_with_aliases(effective_name);
let final_name = if primary.is_empty() { effective_name.to_string() } else { primary };
// 跳过字符串 <= 2 的人名(太短不像人名)
if final_name.chars().count() <= 2 {
@@ -366,7 +372,7 @@ pub async fn phase_parse_dirty(db: &Database, dirty_set: &DirtySet) -> (usize, u
}
let mut tx = db.pool.begin().await.expect("begin tx");
db.update_album_person_with_tx(&mut tx, &album.id, name, &final_name).await;
db.update_album_person_with_tx(&mut tx, &album.id, effective_name, &final_name).await;
let pid = db.insert_person_with_tx(&mut tx, &final_name, None).await;
// 先清旧关联:删除该相册的所有旧 person_album 记录
db.delete_album_person_albums_with_tx(&mut tx, &album.id).await;

View File

@@ -275,6 +275,24 @@ impl TagDict {
|| self.included_person_names.contains(&name_lower)
}
/// 在 include 列表中查找以 name 开头的最长匹配。
///
/// 例如 include 中有 "杨晨晨Yome", "杨晨晨Sugar",
/// 传入 "杨晨晨" 会返回 "杨晨晨Yome"(取最长的那条)。
/// 传入 "Yome" 也返回 "杨晨晨Yome"(取包含该词的最长的那条)。
pub fn find_longest_included_match(&self, name: &str) -> Option<String> {
let name_lower = name.to_lowercase();
self.included_person_names.iter()
.filter(|included| {
let inc_lower = included.to_lowercase();
// include 以 name 开头 ? 或 name 以 include 开头 ?
inc_lower.starts_with(&name_lower) || name_lower.starts_with(&inc_lower)
|| inc_lower.contains(&name_lower) // include 包含 name(中文核心→全名)
})
.max_by_key(|s| s.len())
.cloned()
}
/// 获取强制包含人名集合
pub fn get_included_persons(&self) -> &HashSet<String> {
&self.included_person_names

View File

@@ -291,8 +291,11 @@ pub fn is_likely_person_name(name: &str) -> bool {
if name.is_empty() { return false; }
// 强制包含名单优先放行(已知模特名,跳过所有启发式检查)
// 同时支持通过更长匹配扩展 name(如 "杨晨晨" → "杨晨晨Yome")
let dict = tag_dict::get_tag_dict();
if dict.is_included_person(name) { return true; }
if dict.is_included_person(name) || dict.find_longest_included_match(name).is_some() {
return true;
}
// 字符数必须 >= 3(人名至少需要 2 个中文字或 3 个英文字母)
if name.chars().count() <= 2 { return false; }