feat: 增加剧名杂音清理规则配置项,清理搜索与匹配阶段的剧名杂音词 (#368)
* feat: 增加剧名杂音清理规则配置项,清理搜索与匹配阶段的剧名杂音词 括号内画质/配音/版本等杂音词(如臻彩、高清、国配)阻塞 搜索和标题匹配。清洗分两层: 1. 搜索输入阶段:searchAnime 获取用户关键词后即清理再提交源站 2. 标题匹配阶段:titleMatches 对源标题和查询词双端清理后再比较 新增 TITLE_NOISE_FILTER 环境变量,值为正则表达式。 默认规则使用字符类 [((]...[))] 同时匹配中英文括号。 不设置时使用默认规则,设为空可禁用。 * fix: 限制剧集匹配中直播一词正则,避免误伤正常标题 EPISODE_TITLE_FILTER 中直播(陪看|回顾)? 匹配裸"直播" 导致"昭演女高 直播欺师"被误过滤。去掉了 ? 和裸直播 匹配分支,仅保留直播陪看、直播回顾等明确杂音后缀。 同时更新 .env.example 与 README 默认值。 * fix: matchAnime 标题未做杂音清理,导致含杂音词文件名匹配失败 matchAnime 提取标题后未清理画质/配音等杂音词,直接传入 matchAniAndEp 和 matchSeason 做 includes 匹配。 杂音词经 normalizeSpaces 去括号后内容残留,阻塞匹配。 在 TITLE_MAPPING_TABLE 和繁转简之后插入噪音清理, 所有下游函数自动受益。searchAnime 保持独立的搜索词清理。
This commit is contained in:
1 parent
2163d7b5f4
commit
3345ed190a
5 files changed
+87
-5
No files matched your search
@@ -418,6 +418,7 @@ API 支持返回 Bilibili 标准 XML 格式的弹幕数据,通过查询参数
|
||||
| STRICT_TITLE_MATCH | 【可选】是否启用严格标题匹配模式,默认为`false`(宽松模糊匹配),启用后只匹配标题开头或完全匹配的结果。例如:搜索"遮天"时,`false`会匹配"古惑仔3之只手遮天",`true`只匹配"遮天"、"遮天 第一季"等。可选值:`true`、`false` |
|
||||
| TITLE_TO_CHINESE | 【可选】是否在match自动匹配时将外语标题转换成中文标题,适用于网盘没有刮削的资源,默认值:false(不转换),说明:需配合TMDB_API_KEY使用 |
|
||||
| TITLE_MAPPING_TABLE | 【可选】剧名映射表,用于自动匹配时替换标题进行搜索,格式:原始标题->映射标题;原始标题->映射标题;... ,例如:"唐朝诡事录->唐朝诡事录之西行;国色芳华->锦绣芳华" |
|
||||
| TITLE_NOISE_FILTER | 【可选】剧名杂音清理规则,按正则表达式清理搜索与匹配阶段的剧名杂音词(如`百花杀(真彩)`→`百花杀`),默认值如下,设为空值可禁用 |
|
||||
| ANIME_TITLE_SIMPLIFIED | 【可选】是否在搜索时将繁体剧名标题自动转换为简体,适用于繁体标题搜索,默认值:false(不转换),可选值:`true`、`false` |
|
||||
| BLOCKED_WORDS | 【可选】弹幕屏蔽词列表,默认为空,示例如下 |
|
||||
| GROUP_MINUTE | 【可选】合并去重分钟数,表示按n分钟分组后对弹幕合并去重,默认为1,最大值为30,0表示不去重 |
|
||||
@@ -455,12 +456,17 @@ API 支持返回 Bilibili 标准 XML 格式的弹幕数据,通过查询参数
|
||||
|
||||
```regex
|
||||
# EPISODE_TITLE_FILTER 默认值
|
||||
(特别|惊喜|纳凉)?企划(?!(书|案|部))|合伙人手记|超前(营业|vlog)?|速览|vlog|(?<!(Chain|Chemical|Nuclear|连锁|化学|核|生化|生理|应激))reaction|(?<!(单))纯享|加更(版|篇)?|抢先(看|版|集|篇)?|(?<!(被|争|谁))抢[先鲜](?!(一步|手|攻|了|告|言|机|话))|抢鲜|预告(?!(函|信|书|犯))|(?<!(死亡|恐怖|灵异|怪谈))花絮(独家)?|(?<!(一|直))直拍|(制作|拍摄|幕后|花絮|未播|独家|演员|导演|主创|杀青|探班|收官|开播|先导|彩蛋|NG|回顾|高光|个人|主创)特辑|(?<!(行动|计划|游戏|任务|危机|神秘|黄金))彩蛋|(?<!(嫌疑人|证人|家属|律师|警方|凶手|死者))专访|(?<!(证人))采访(?!(吸血鬼|鬼))|(正式|角色|先导|概念|首曝|定档|剧情|动画|宣传|主题曲|印象)[\s\.]*[PpPp][VvVv]|(?<!(退居|回归|走向|转战|隐身|藏身|的))幕后(?!(主谋|主使|黑手|真凶|玩家|老板|金主|英雄|功臣|推手|大佬|操纵|交易|策划|博弈|BOSS|真相))(故事|花絮|独家)?|直播(陪看|回顾)?|直播(?!(.*(事件|杀人|自杀|谋杀|犯罪|现场|游戏|挑战)))|未播(片段)?|衍生(?!(品|物|兽))|番外(?!(地|人))|会员(专享|加长|尊享|专属|版)?|(?<!(鸦|雪|纸|相|照|图|名|大))片花|(?<!(提取|吸收|生命|魔法|修护|美白))精华|看点|速看|解读(?!.*(密文|密码|密电|电报|档案|书信|遗书|碑文|代码|信号|暗号|讯息|谜题|人心|唇语|真相|谜团|梦境))|(?<!(案情|人生|死前|历史|世纪))回顾|影评|解说|吐槽|(?<!(年终|季度|库存|资产|物资|财务|收获|战利))盘点|拍摄花絮|制作花絮|幕后花絮|未播花絮|独家花絮|花絮特辑|先导预告|终极预告|正式预告|官方预告|彩蛋片段|删减片段|未播片段|番外彩蛋|精彩片段|精彩看点|精彩集锦|看点解析|看点预告|NG镜头|NG花絮|番外篇|番外特辑|制作特辑|拍摄特辑|幕后特辑|导演特辑|演员特辑|片尾曲|(?<!(生命|生活|情感|爱情|一段|小|意外))插曲|高光回顾|背景音乐|OST|音乐MV|歌曲MV|前季回顾|剧情回顾|往期回顾|内容总结|剧情盘点|精选合集|剪辑合集|混剪视频|独家专访|演员访谈|导演访谈|主创访谈|媒体采访|发布会采访|陪看(记)?|试看版|短剧|精编|(?<!(Love|Disney|One|C|Note|S\d+|\+|&|\s))Plus|独家版|(?<!(导演|加长|周年))特别版(?!(图|画))|短片|(?<!(新闻|紧急|临时|召开|破坏|大闹|澄清|道歉|新品|产品|事故))发布会|解忧局|走心局|火锅局|巅峰时刻|坞里都知道|福持目标坞民|福利(?!(院|会|主义|课))篇|(福利|加更|番外|彩蛋|衍生|特别|收官|游戏|整蛊|日常)篇|独家(?!(记忆|试爱|报道|秘方|占有|宠爱|恩宠))|.{2,}(?<!(市|分|警|总|省|卫|药|政|监|结|大|开|破|布|僵|困|骗|赌|胜|败|定|乱|危|迷|谜|入|搅|设|中|残|平|和|终|变|对|安|做|书|画|察|务|案|通|信|育|商|象|源|业|冰))局(?!(长|座|势|面|部|内|外|中|限|促|气))|(?<!(重症|隔离|实验|心理|审讯|单向|术后))观察室|上班那点事儿|周top|赛段|VLOG|(?<!(大案|要案|刑侦|侦查|破案|档案|风云|历史|战争|探案|自然|人文|科学|医学|地理|宇宙|赛事|世界杯|奥运))全纪录|开播|先导|总宣|展演|集锦|旅行日记|精彩分享|剧情揭秘(?!(者|人))|(?:^|】\s*|\]\s*)(?:[SC]|SP|OP|ED|PV)\d+(?:[\s::\.\-]|$)
|
||||
(特别|惊喜|纳凉)?企划(?!(书|案|部))|合伙人手记|超前(营业|vlog)?|速览|vlog|(?<!(Chain|Chemical|Nuclear|连锁|化学|核|生化|生理|应激))reaction|(?<!(单))纯享|加更(版|篇)?|抢先(看|版|集|篇)?|(?<!(被|争|谁))抢[先鲜](?!(一步|手|攻|了|告|言|机|话))|抢鲜|预告(?!(函|信|书|犯))|(?<!(死亡|恐怖|灵异|怪谈))花絮(独家)?|(?<!(一|直))直拍|(制作|拍摄|幕后|花絮|未播|独家|演员|导演|主创|杀青|探班|收官|开播|先导|彩蛋|NG|回顾|高光|个人|主创)特辑|(?<!(行动|计划|游戏|任务|危机|神秘|黄金))彩蛋|(?<!(嫌疑人|证人|家属|律师|警方|凶手|死者))专访|(?<!(证人))采访(?!(吸血鬼|鬼))|(正式|角色|先导|概念|首曝|定档|剧情|动画|宣传|主题曲|印象)[\s\.]*[PpPp][VvVv]|(?<!(退居|回归|走向|转战|隐身|藏身|的))幕后(?!(主谋|主使|黑手|真凶|玩家|老板|金主|英雄|功臣|推手|大佬|操纵|交易|策划|博弈|BOSS|真相))(故事|花絮|独家)?|直播(陪看|回顾)|未播(片段)?|衍生(?!(品|物|兽))|番外(?!(地|人))|会员(专享|加长|尊享|专属|版)?|(?<!(鸦|雪|纸|相|照|图|名|大))片花|(?<!(提取|吸收|生命|魔法|修护|美白))精华|看点|速看|解读(?!.*(密文|密码|密电|电报|档案|书信|遗书|碑文|代码|信号|暗号|讯息|谜题|人心|唇语|真相|谜团|梦境))|(?<!(案情|人生|死前|历史|世纪))回顾|影评|解说|吐槽|(?<!(年终|季度|库存|资产|物资|财务|收获|战利))盘点|拍摄花絮|制作花絮|幕后花絮|未播花絮|独家花絮|花絮特辑|先导预告|终极预告|正式预告|官方预告|彩蛋片段|删减片段|未播片段|番外彩蛋|精彩片段|精彩看点|精彩集锦|看点解析|看点预告|NG镜头|NG花絮|番外篇|番外特辑|制作特辑|拍摄特辑|幕后特辑|导演特辑|演员特辑|片尾曲|(?<!(生命|生活|情感|爱情|一段|小|意外))插曲|高光回顾|背景音乐|OST|音乐MV|歌曲MV|前季回顾|剧情回顾|往期回顾|内容总结|剧情盘点|精选合集|剪辑合集|混剪视频|独家专访|演员访谈|导演访谈|主创访谈|媒体采访|发布会采访|陪看(记)?|试看版|短剧|精编|(?<!(Love|Disney|One|C|Note|S\d+|\+|&|\s))Plus|独家版|(?<!(导演|加长|周年))特别版(?!(图|画))|短片|(?<!(新闻|紧急|临时|召开|破坏|大闹|澄清|道歉|新品|产品|事故))发布会|解忧局|走心局|火锅局|巅峰时刻|坞里都知道|福持目标坞民|福利(?!(院|会|主义|课))篇|(福利|加更|番外|彩蛋|衍生|特别|收官|游戏|整蛊|日常)篇|独家(?!(记忆|试爱|报道|秘方|占有|宠爱|恩宠))|.{2,}(?<!(市|分|警|总|省|卫|药|政|监|结|大|开|破|布|僵|困|骗|赌|胜|败|定|乱|危|迷|谜|入|搅|设|中|残|平|和|终|变|对|安|做|书|画|察|务|案|通|信|育|商|象|源|业|冰))局(?!(长|座|势|面|部|内|外|中|限|促|气))|(?<!(重症|隔离|实验|心理|审讯|单向|术后))观察室|上班那点事儿|周top|赛段|VLOG|(?<!(大案|要案|刑侦|侦查|破案|档案|风云|历史|战争|探案|自然|人文|科学|医学|地理|宇宙|赛事|世界杯|奥运))全纪录|开播|先导|总宣|展演|集锦|旅行日记|精彩分享|剧情揭秘(?!(者|人))|(?:^|】\s*|\]\s*)(?:[SC]|SP|OP|ED|PV)\d+(?:[\s::\.\-]|$)
|
||||
|
||||
# 如果你想自定义过滤词,请新增EPISODE_TITLE_FILTER环境变量,示例如下,每个词用'|'隔开,也可参照默认值填写
|
||||
测试|test
|
||||
```
|
||||
|
||||
```plain
|
||||
# TITLE_NOISE_FILTER 默认值
|
||||
[((](?:臻彩|真彩|高清|标清|超清|国配|中配|日配|粤语|原声|台配|无修|未删减|完整版)[))]
|
||||
```
|
||||
|
||||
```regex
|
||||
# BLOCKED_WORDS 示例值
|
||||
/.{20,}/,/^\d{2,4}[-/.]\d{1,2}[-/.]\d{1,2}([日号.]*)?$/,/^(?!哈+$)([a-zA-Z\u4e00-\u9fa5])\1{2,}/,/[0-9]+\.*[0-9]*\s*(w|万)+\s*(\+|个|人|在看)+/,/^[a-z]{6,}$/,/^(?:qwertyuiop|asdfghjkl|zxcvbnm)$/,/^\d{5,}$/,/^(\d)\1{2,}$/,/^\d{1,4}$/,/(20[0-3][0-9])/,/(0?[1-9]|1[0-2])月/,/\d{1,2}[.-]\d{1,2}/,/[@#&$%^*+\|/\-_=<>°◆◇■□●○★☆▼▲♥♦♠♣①②③④⑤⑥⑦⑧⑨⑩]/,/[一二三四五六七八九十百\d]+刷/,/第[一二三四五六七八九十百\d]+/,/(全体成员|报到|报道|来啦|签到|刷|打卡|我在|来了|考古|爱了|挖坟|留念|你好|回来|哦哦|重温|复习|重刷|再看|在看|前排|沙发|有人看|板凳|末排|我老婆|我老公|撅了|后排|周目|重看|包养|DVD|同上|同样|我也是|俺也|算我|爱豆|我家爱豆|我家哥哥|加我|三连|币|新人|入坑|补剧|冲了|硬了|看完|舔屏|万人|牛逼|煞笔|傻逼|卧槽|tm|啊这|哇哦)/
|
||||
|
||||
+11
-1
@@ -122,7 +122,7 @@ SOURCE_ORDER=douban,360,renren,hanjutv
|
||||
# - 可以直接修改下方规则,按需增删关键词
|
||||
# 示例:只过滤预告和花絮
|
||||
# EPISODE_TITLE_FILTER=预告|花絮
|
||||
EPISODE_TITLE_FILTER=(特别|惊喜|纳凉)?企划(?!(书|案|部))|合伙人手记|超前(营业|vlog)?|速览|vlog|(?<!(Chain|Chemical|Nuclear|连锁|化学|核|生化|生理|应激))reaction|(?<!(单))纯享|加更(版|篇)?|抢先(看|版|集|篇)?|(?<!(被|争|谁))抢[先鲜](?!(一步|手|攻|了|告|言|机|话))|抢鲜|预告(?!(函|信|书|犯))|(?<!(死亡|恐怖|灵异|怪谈))花絮(独家)?|(?<!(一|直))直拍|(制作|拍摄|幕后|花絮|未播|独家|演员|导演|主创|杀青|探班|收官|开播|先导|彩蛋|NG|回顾|高光|个人|主创)特辑|(?<!(行动|计划|游戏|任务|危机|神秘|黄金))彩蛋|(?<!(嫌疑人|证人|家属|律师|警方|凶手|死者))专访|(?<!(证人))采访(?!(吸血鬼|鬼))|(正式|角色|先导|概念|首曝|定档|剧情|动画|宣传|主题曲|印象)[\s\.]*[PpPp][VvVv]|(?<!(退居|回归|走向|转战|隐身|藏身|的))幕后(?!(主谋|主使|黑手|真凶|玩家|老板|金主|英雄|功臣|推手|大佬|操纵|交易|策划|博弈|BOSS|真相))(故事|花絮|独家)?|直播(陪看|回顾)?|直播(?!(.*(事件|杀人|自杀|谋杀|犯罪|现场|游戏|挑战)))|未播(片段)?|衍生(?!(品|物|兽))|番外(?!(地|人))|会员(专享|加长|尊享|专属|版)?|(?<!(鸦|雪|纸|相|照|图|名|大))片花|(?<!(提取|吸收|生命|魔法|修护|美白))精华|看点|速看|解读(?!.*(密文|密码|密电|电报|档案|书信|遗书|碑文|代码|信号|暗号|讯息|谜题|人心|唇语|真相|谜团|梦境))|(?<!(案情|人生|死前|历史|世纪))回顾|影评|解说|吐槽|(?<!(年终|季度|库存|资产|物资|财务|收获|战利))盘点|拍摄花絮|制作花絮|幕后花絮|未播花絮|独家花絮|花絮特辑|先导预告|终极预告|正式预告|官方预告|彩蛋片段|删减片段|未播片段|番外彩蛋|精彩片段|精彩看点|精彩集锦|看点解析|看点预告|NG镜头|NG花絮|番外篇|番外特辑|制作特辑|拍摄特辑|幕后特辑|导演特辑|演员特辑|片尾曲|(?<!(生命|生活|情感|爱情|一段|小|意外))插曲|高光回顾|背景音乐|OST|音乐MV|歌曲MV|前季回顾|剧情回顾|往期回顾|内容总结|剧情盘点|精选合集|剪辑合集|混剪视频|独家专访|演员访谈|导演访谈|主创访谈|媒体采访|发布会采访|陪看(记)?|试看版|短剧|精编|(?<!(Love|Disney|One|C|Note|S\d+|\+|&|\s))Plus|独家版|(?<!(导演|加长|周年))特别版(?!(图|画))|短片|(?<!(新闻|紧急|临时|召开|破坏|大闹|澄清|道歉|新品|产品|事故))发布会|解忧局|走心局|火锅局|巅峰时刻|坞里都知道|福持目标坞民|福利(?!(院|会|主义|课))篇|(福利|加更|番外|彩蛋|衍生|特别|收官|游戏|整蛊|日常)篇|独家(?!(记忆|试爱|报道|秘方|占有|宠爱|恩宠))|.{2,}(?<!(市|分|警|总|省|卫|药|政|监|结|大|开|破|布|僵|困|骗|赌|胜|败|定|乱|危|迷|谜|入|搅|设|中|残|平|和|终|变|对|安|做|书|画|察|务|案|通|信|育|商|象|源|业|冰))局(?!(长|座|势|面|部|内|外|中|限|促|气))|(?<!(重症|隔离|实验|心理|审讯|单向|术后))观察室|上班那点事儿|周top|赛段|VLOG|(?<!(大案|要案|刑侦|侦查|破案|档案|风云|历史|战争|探案|自然|人文|科学|医学|地理|宇宙|赛事|世界杯|奥运))全纪录|开播|先导|总宣|展演|集锦|旅行日记|精彩分享|剧情揭秘(?!(者|人))|(?:^|】\s*|\]\s*)(?:[SC]|SP|OP|ED|PV)\d+(?:[\s::\.\-]|$)
|
||||
EPISODE_TITLE_FILTER=(特别|惊喜|纳凉)?企划(?!(书|案|部))|合伙人手记|超前(营业|vlog)?|速览|vlog|(?<!(Chain|Chemical|Nuclear|连锁|化学|核|生化|生理|应激))reaction|(?<!(单))纯享|加更(版|篇)?|抢先(看|版|集|篇)?|(?<!(被|争|谁))抢[先鲜](?!(一步|手|攻|了|告|言|机|话))|抢鲜|预告(?!(函|信|书|犯))|(?<!(死亡|恐怖|灵异|怪谈))花絮(独家)?|(?<!(一|直))直拍|(制作|拍摄|幕后|花絮|未播|独家|演员|导演|主创|杀青|探班|收官|开播|先导|彩蛋|NG|回顾|高光|个人|主创)特辑|(?<!(行动|计划|游戏|任务|危机|神秘|黄金))彩蛋|(?<!(嫌疑人|证人|家属|律师|警方|凶手|死者))专访|(?<!(证人))采访(?!(吸血鬼|鬼))|(正式|角色|先导|概念|首曝|定档|剧情|动画|宣传|主题曲|印象)[\s\.]*[PpPp][VvVv]|(?<!(退居|回归|走向|转战|隐身|藏身|的))幕后(?!(主谋|主使|黑手|真凶|玩家|老板|金主|英雄|功臣|推手|大佬|操纵|交易|策划|博弈|BOSS|真相))(故事|花絮|独家)?|直播(陪看|回顾)|未播(片段)?|衍生(?!(品|物|兽))|番外(?!(地|人))|会员(专享|加长|尊享|专属|版)?|(?<!(鸦|雪|纸|相|照|图|名|大))片花|(?<!(提取|吸收|生命|魔法|修护|美白))精华|看点|速看|解读(?!.*(密文|密码|密电|电报|档案|书信|遗书|碑文|代码|信号|暗号|讯息|谜题|人心|唇语|真相|谜团|梦境))|(?<!(案情|人生|死前|历史|世纪))回顾|影评|解说|吐槽|(?<!(年终|季度|库存|资产|物资|财务|收获|战利))盘点|拍摄花絮|制作花絮|幕后花絮|未播花絮|独家花絮|花絮特辑|先导预告|终极预告|正式预告|官方预告|彩蛋片段|删减片段|未播片段|番外彩蛋|精彩片段|精彩看点|精彩集锦|看点解析|看点预告|NG镜头|NG花絮|番外篇|番外特辑|制作特辑|拍摄特辑|幕后特辑|导演特辑|演员特辑|片尾曲|(?<!(生命|生活|情感|爱情|一段|小|意外))插曲|高光回顾|背景音乐|OST|音乐MV|歌曲MV|前季回顾|剧情回顾|往期回顾|内容总结|剧情盘点|精选合集|剪辑合集|混剪视频|独家专访|演员访谈|导演访谈|主创访谈|媒体采访|发布会采访|陪看(记)?|试看版|短剧|精编|(?<!(Love|Disney|One|C|Note|S\d+|\+|&|\s))Plus|独家版|(?<!(导演|加长|周年))特别版(?!(图|画))|短片|(?<!(新闻|紧急|临时|召开|破坏|大闹|澄清|道歉|新品|产品|事故))发布会|解忧局|走心局|火锅局|巅峰时刻|坞里都知道|福持目标坞民|福利(?!(院|会|主义|课))篇|(福利|加更|番外|彩蛋|衍生|特别|收官|游戏|整蛊|日常)篇|独家(?!(记忆|试爱|报道|秘方|占有|宠爱|恩宠))|.{2,}(?<!(市|分|警|总|省|卫|药|政|监|结|大|开|破|布|僵|困|骗|赌|胜|败|定|乱|危|迷|谜|入|搅|设|中|残|平|和|终|变|对|安|做|书|画|察|务|案|通|信|育|商|象|源|业|冰))局(?!(长|座|势|面|部|内|外|中|限|促|气))|(?<!(重症|隔离|实验|心理|审讯|单向|术后))观察室|上班那点事儿|周top|赛段|VLOG|(?<!(大案|要案|刑侦|侦查|破案|档案|风云|历史|战争|探案|自然|人文|科学|医学|地理|宇宙|赛事|世界杯|奥运))全纪录|开播|先导|总宣|展演|集锦|旅行日记|精彩分享|剧情揭秘(?!(者|人))|(?:^|】\s*|\]\s*)(?:[SC]|SP|OP|ED|PV)\d+(?:[\s::\.\-]|$)
|
||||
# ==================== 屏蔽词配置 ====================
|
||||
# 屏蔽词列表(用于过滤弹幕内容)
|
||||
# 默认值:空
|
||||
@@ -383,6 +383,16 @@ ANIME_TITLE_SIMPLIFIED=false
|
||||
# 说明:使用 | 分隔多个关键词,例如:广告|预告|无关剧名
|
||||
ANIME_TITLE_FILTER=
|
||||
|
||||
# 剧名杂音清理规则(按正则表达式清理搜索与匹配阶段的剧名杂音词,如`百花杀(真彩)`→`百花杀`)
|
||||
# 默认值:下方完整规则
|
||||
# 说明:
|
||||
# - 如果设置了此环境变量,将完全覆盖默认规则(不是增量添加)
|
||||
# - 可以直接修改下方规则,按需增删关键词
|
||||
# 示例:只清理括号臻彩和真彩
|
||||
# TITLE_NOISE_FILTER=[((](?:臻彩|真彩)[))]
|
||||
# 设为空值可禁用
|
||||
TITLE_NOISE_FILTER=[((](?:臻彩|真彩|高清|标清|超清|国配|中配|日配|粤语|原声|台配|无修|未删减|完整版)[))]
|
||||
|
||||
# ==================== AI 配置 ====================
|
||||
|
||||
# AI服务的基础URL地址,用于配置AI相关功能的API端点
|
||||
|
||||
@@ -440,6 +440,12 @@ async function executeSourceHandlers(resultData, queryTitle, targetAnimesList, r
|
||||
// Extracted function for GET /api/v2/search/anime
|
||||
export async function searchAnime(url, preferAnimeId = null, preferSource = null, detailStore = null, targetPlatform = null) {
|
||||
let queryTitle = url.searchParams.get("keyword");
|
||||
|
||||
// 搜索词杂音清理:移除画质/配音/版本等杂音词后再提交源站搜索
|
||||
if (globals.titleNoiseFilter) {
|
||||
queryTitle = queryTitle.replace(globals.titleNoiseFilter, '').trim();
|
||||
}
|
||||
|
||||
let querySeason = url.searchParams.get("season");
|
||||
querySeason = querySeason ? parseInt(querySeason, 10) : null;
|
||||
let queryEpisode = url.searchParams.get("episode");
|
||||
@@ -1530,6 +1536,11 @@ export async function matchAnime(url, req, clientIp) {
|
||||
title = simplifiedTitle;
|
||||
}
|
||||
|
||||
// 剧名杂音清理:移除画质/配音/版本等杂音词
|
||||
if (globals.titleNoiseFilter) {
|
||||
title = title.replace(globals.titleNoiseFilter, '').trim();
|
||||
}
|
||||
|
||||
// 获取 prefer animeId(按 season 维度)
|
||||
const [preferAnimeId, preferSource, offsets] = getPreferAnimeId(title, season);
|
||||
log("info", `[system] [Match] prefer animeId: ${preferAnimeId} from ${preferSource}`);
|
||||
|
||||
@@ -345,7 +345,7 @@ export class Envs {
|
||||
|
||||
// [3] 幕后/衍生/直播防御,保护: 幕后主谋, 番外地, 直播杀人/犯罪
|
||||
'(?<!(退居|回归|走向|转战|隐身|藏身|的))幕后(?!(主谋|主使|黑手|真凶|玩家|老板|金主|英雄|功臣|推手|大佬|操纵|交易|策划|博弈|BOSS|真相))(故事|花絮|独家)?|' +
|
||||
'衍生(?!(品|物|兽))|番外(?!(地|人))|直播(陪看|回顾)?|直播(?!(.*(事件|杀人|自杀|谋杀|犯罪|现场|游戏|挑战)))|' +
|
||||
'衍生(?!(品|物|兽))|番外(?!(地|人))|直播(陪看|回顾)|' +
|
||||
'未播(片段)?|会员(专享|加长|尊享|专属|版)?|' +
|
||||
|
||||
// [4] 解读/回顾/盘点防御,保护: 生命精华, 案情回顾, 财务盘点, 新闻发布会
|
||||
@@ -533,6 +533,30 @@ export class Envs {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析剧名杂音清理规则
|
||||
* 移除搜索关键词和源标题中的画质/配音/版本等杂音词。
|
||||
* 支持完全自定义的正则表达式,默认为同时匹配中英文括号的常用杂音词。
|
||||
* 未设置时使用默认规则,设为空值可禁用。
|
||||
* @returns {RegExp|null} 全局正则,显式设为空时返回 null(禁用)
|
||||
*/
|
||||
static resolveTitleNoiseFilter() {
|
||||
const defaultPattern = '[((](?:臻彩|真彩|高清|标清|超清|国配|中配|日配|粤语|原声|台配|无修|未删减|完整版)[))]';
|
||||
const raw = this.get('TITLE_NOISE_FILTER', '', 'string').trim();
|
||||
const hasKey = (this.env && 'TITLE_NOISE_FILTER' in this.env)
|
||||
|| (typeof process !== 'undefined' && 'TITLE_NOISE_FILTER' in process.env);
|
||||
|
||||
if (!raw) {
|
||||
if (hasKey) { this.accessedEnvVars.set('TITLE_NOISE_FILTER', ''); return null; }
|
||||
this.accessedEnvVars.set('TITLE_NOISE_FILTER', defaultPattern);
|
||||
} else {
|
||||
this.accessedEnvVars.set('TITLE_NOISE_FILTER', raw);
|
||||
}
|
||||
|
||||
try { return new RegExp(raw || defaultPattern, 'gi'); }
|
||||
catch (e) { console.warn('Invalid TITLE_NOISE_FILTER regex, using default.'); try { return new RegExp(defaultPattern, 'gi'); } catch (e2) { return null; } }
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取记录的原始环境变量 JSON
|
||||
* @returns {Map<any, any>} JSON 字符串
|
||||
@@ -613,6 +637,7 @@ export class Envs {
|
||||
'TITLE_TO_CHINESE': { category: 'match', type: 'boolean', description: '外语标题转换中文开关' },
|
||||
'ANIME_TITLE_SIMPLIFIED': { category: 'match', type: 'boolean', description: '搜索的剧名标题自动繁转简' },
|
||||
'TITLE_MAPPING_TABLE': { category: 'match', type: 'map', description: '剧名映射表,用于自动匹配时替换标题进行搜索,格式:原始标题->映射标题;原始标题->映射标题;... ,例如:"唐朝诡事录->唐朝诡事录之西行;国色芳华->锦绣芳华"' },
|
||||
'TITLE_NOISE_FILTER': { category: 'match', type: 'text', description: '剧名杂音清理规则,按正则表达式清理搜索与匹配阶段的剧名杂音词(如`百花杀(真彩)`→`百花杀`)。默认值:[((](?:臻彩|真彩|高清|标清|超清|国配|中配|日配|粤语|原声|台配|无修|未删减|完整版)[))],中英文括号均匹配。设为空值可禁用' },
|
||||
'AI_BASE_URL': { category: 'match', type: 'text', description: 'AI服务基础URL,不填默认为https://api.openai.com/v1' },
|
||||
'AI_MODEL': { category: 'match', type: 'text', description: 'AI模型名称,不填默认为gpt-4o' },
|
||||
'AI_API_KEY': { category: 'match', type: 'text', description: 'AI服务API密钥,默认为空,需手动填写' },
|
||||
@@ -673,6 +698,7 @@ export class Envs {
|
||||
platformOrderArr: this.resolvePlatformOrder(), // 自动匹配优选平台
|
||||
animeTitleFilter: this.resolveAnimeTitleFilter(), // 剧名正则过滤
|
||||
episodeTitleFilter: this.resolveEpisodeTitleFilter(), // 剧集标题正则过滤
|
||||
titleNoiseFilter: this.resolveTitleNoiseFilter(), // 剧名杂音清理规则
|
||||
blockedWords: this.get('BLOCKED_WORDS', '', 'string'), // 屏蔽词列表
|
||||
groupMinute: Math.min(this.get('GROUP_MINUTE', 1, 'number'), 30), // 分钟内合并去重(默认 1,最大值30,0表示不去重)
|
||||
danmuLimit: this.get('DANMU_LIMIT', 0, 'number'), // 等间隔采样限制弹幕总数,单位为k,即千:默认 0,表示不限制弹幕数,若改为5,弹幕总数在超过5000的情况下会将弹幕数控制在5000
|
||||
|
||||
@@ -267,8 +267,12 @@ export function titleMatches(title, query, parsedSeason = null) {
|
||||
// 策略1:严格模式仅允许头部或完全匹配
|
||||
if (globals.strictTitleMatch) return strictTitleMatch(title, query);
|
||||
|
||||
// 剧名杂音清理:移除画质/配音/版本等杂音词,避免阻塞匹配
|
||||
const tagFilter = globals.titleNoiseFilter || null;
|
||||
const cleanTitle = tagFilter ? title.replace(tagFilter, '').trim() : title;
|
||||
|
||||
// 预处理:移除干扰字符并转小写,消除格式与大小写差异
|
||||
const t = normalizeSpaces(title).toLowerCase();
|
||||
const t = normalizeSpaces(cleanTitle).toLowerCase();
|
||||
const q = normalizeSpaces(query).toLowerCase();
|
||||
|
||||
// 预处理:构建搜索词变种池 (原词、简体、繁体),利用 Set 去重
|
||||
@@ -290,6 +294,15 @@ export function titleMatches(title, query, parsedSeason = null) {
|
||||
}
|
||||
}
|
||||
|
||||
// 查询词含杂音词时,将清理后的干净查询词加入候选池
|
||||
// 如"百花杀(真彩)"→ 追加"百花杀",避免"真彩"二字导致包含匹配失败
|
||||
if (tagFilter) {
|
||||
const tagStripped = query.replace(tagFilter, '').trim();
|
||||
if (tagStripped && tagStripped !== query) {
|
||||
qList = [...new Set([...qList, normalizeSpaces(tagStripped).toLowerCase()])];
|
||||
}
|
||||
}
|
||||
|
||||
// 季度特征校验:先于包含匹配执行,确保错误季度的标题不会因干净查询词误通过
|
||||
if (querySeason !== null) {
|
||||
const titleSeason = getExplicitSeasonNumber(title);
|
||||
@@ -307,7 +320,7 @@ export function titleMatches(title, query, parsedSeason = null) {
|
||||
if (qList.some(kw => t.includes(kw))) return true;
|
||||
|
||||
// 策略3:相似度匹配 (阈值0.8)
|
||||
return qList.some(kw => {
|
||||
const simMatch = qList.some(kw => {
|
||||
// 长度差异过大,或纯英文/数字时,禁止使用相似度计算策略
|
||||
if (Math.abs(t.length - kw.length) > Math.max(t.length, kw.length) * 0.7 || /^[a-zA-Z0-9]+$/.test(kw)) {
|
||||
return false;
|
||||
@@ -327,6 +340,22 @@ export function titleMatches(title, query, parsedSeason = null) {
|
||||
|
||||
return (matchCount / kw.length) > 0.8;
|
||||
});
|
||||
|
||||
// 年份噪音兜底:前序策略均未命中时,尝试去年份后再次包含匹配
|
||||
// 如查询词含杂音年份"(2026)"但源标题不含,去年后可正常命中
|
||||
if (!simMatch) {
|
||||
const yearStripped = query.replace(/[\(\(]\s*(?:19|20)\d{2}\s*[\)\)]|\b(?:19|20)\d{2}\b/g, '').trim();
|
||||
if (yearStripped && yearStripped !== query) {
|
||||
// 去年份后可能残留杂音词,继续用配置的正则去除
|
||||
const cleanYear = tagFilter ? yearStripped.replace(tagFilter, '').trim() : yearStripped;
|
||||
const yearQ = normalizeSpaces(cleanYear).toLowerCase();
|
||||
// 仅当标题不含年份时才接受兜底,保留用户刻意用年份过滤的语义
|
||||
const titleHasYear = /[\(\(]\s*(?:19|20)\d{2}\s*[\)\)]|\b(?:19|20)\d{2}\b/.test(title);
|
||||
if (yearQ && t.includes(yearQ) && !titleHasYear) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user