- 新表 identify_words(0094):全局一块 + 每部作品一块原文,带版本与审计;episode_mapping_rule 转成文本行后删表
- 全局识别词移植 MP WordsMatcher(屏蔽 / 替换 / 集数偏移 / 替换+偏移 / {[tmdbid=…]}),所有按标题 / 文件名识别的地方解析前套用,命中的行记在解析结果上;保存后后台按改动行重新识别
- 作品识别词:S02 >> S01 EP+24 / S01E13 >> S00E01 / S01 @组 >> 忽略,解析器 + 打印器 + 编译;发布组繁简视为同一个
- 去掉规则自动停用:算出来对不上季表只待确认,要停用就注释掉那一行
- 集数待确认的采用 / 忽略与智能体 apply_rule 改为往作品识别词追加一行(带来历注释)
- 编辑器可视化 / 文本两种模式改同一份原文,保存前试算;作品页「集数映射」用同一个编辑器
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
8.5 KiB
识别词
2026-10-08 定。识别词是给识别用的文本规则,分两级,都在规则页「识别词」页签里看:
- 全局识别词:一块文本,写法与 MoviePilot 的「自定义识别词」一字不差,可以把 MP 的列表直接粘进来。识别前先套到标题与副标题上。
- 作品识别词:每部作品一块文本,写这部作品的季集换算(取代原来散落在作品页的结构化映射规则)。作品页「集数映射」里改的是同一份。
规则照写的用:作品识别词算出来对不上季表的资源保持集数待确认,在预览里标「对不上」,不会自动停用那一行。要停用某一行就把它注释掉。
存储
表 identify_words(迁移 0094):media_entity_id 为空的一行是全局,其余每部作品一行;text 存原文(注释、空行原样保留),version 每次保存 +1,updated_by_* 记最后修改者,reresolve 是全局识别词保存后的后台重算进度。保存要带读到的版本(expectedVersion),别处先改过返回 409;每次保存写审计 identify_words.updated(增删的生效行,各最多 50 行)。
作品识别词在用的时候现场编译成规则(compileEntityWords,contracts),不另存结构化规则。0094 把旧表 episode_mapping_rule 逐作品转成文本行后删表:同季、同换算的多个发布组合成一行,单集对照一行一条,停用的变成注释行,智能体写的上方加一行注释;已有文本时只追加还没有的行。
全局识别词(MP 语法)
逐行处理,前一行的结果交给后一行。每行四种写法之一,# 开头是注释,空行跳过:
| 写法 | 含义 |
|---|---|
国语中字 |
屏蔽词:整行当正则,从标题里删掉 |
A => B |
替换:A 是正则,B 可以用 \1、\g<name> 引用分组,留空就是删掉 |
前 <> 后 >> EP±N |
集数偏移:前后定位词(正则)之间的数字按表达式换算;前导零保留宽度,中文数字仍写中文 |
A => B && 前 <> 后 >> 偏移 |
替换 + 偏移:替换成功才偏移 |
- 标题里偏移不了时偏移副标题:副标题里能直接定位就偏移副标题;定位词出现在「标题 + 副标题」里时只改副标题中会被识别成集数的数字(
第8集、Episode 8、E08、1-12 完结),不动季号和年份。 - 替换词里带
{[tmdbid=…;type=tv|movie;s=季;e=集]}时,解析器把它当显式身份标签:识别直接用这个 TMDB 作品,s/e指定季集,g=指定剧集组。 - 偏移表达式只允许数字、
EP、括号和+ - * / // %,结果取整;2EP、EP(1)这类省略运算符的写法报错;EP区分大小写;不含EP的表达式算出常数(与 MP 一致)。 - 正则按 Python 写法:
(?P<n>…)、(?P=n)、开头的(?i)(?s)(?m)、\A/\Z、\p{Han}等脚本名都转成 JS 写法再编译。 - 写错的行(正则编译不了、偏移表达式不合法)编辑器里标红,但可以保存,套用时跳过这一行(MP 也是套用时才失败)。「替换 + 偏移」的偏移写错时替换照做、这一行不算命中,与 MP 一致。
- 命中的行记在解析结果上(
parsed.words.applied,另记套用前的原标题),集数映射预览、全局试算里显示「命中识别词」。
实现:语法与 Python 正则 / 替换模板 / 算术在 packages/contracts/src/identify-words-syntax.ts,套用引擎移植 MP WordsMatcher 在 packages/domain/src/identify-words/apply.ts,parseRelease(title, { words }) 解析前先套用(parseReleasePath 对文件、上级、上上级目录各自套用)。MP 用例移植在 packages/domain/test/identify-words.test.ts。
在哪里生效
服务端进程内缓存全局识别词(identify-words-cache.ts,5 秒按版本核对一次,本进程保存后立即失效),这些地方解析前都套用:
- 资源识别:站点列表抓取落库、RSS / 列表 / 搜索来的资源识别(
resolveRelease)、手动指定作品、整理元数据补全、集数待确认的同组判断 - 搜索结果的快速筛选、规则组 / 收录版本的试算
- 下载:季包选文件时对种子里的文件名
- 整理:整理计划里每个文件(文件名改了季集时把覆盖值交给命名)、接管下载器里已有的任务
- 文件管理:识别、推荐文件名
- 刮削:未登记文件的季集
- 集数映射:按作品重算、预览、智能体的上下文包
保存后重算
保存时比较生效行(注释、空行之外的行)的增减。有增减才排后台任务 reresolveIdentifyWords:每批 500 条扫全部资源,标题 / 副标题被某个增减的行单独命中的,入队 resolveObservation(强制重新识别,身份与集数都重来,人工锁定的跳过)。进度写回 identify_words.reresolve,规则页每 3 秒刷一次;更新的保存会取代还在跑的那一版。
作品识别词
一行一条,# 开头是注释,空行跳过。三种写法:
S<来源季> [@发布组 …] >> [S<目标季>] <集号表达式> 季集换算
S<季>E<集>[-E<集>] [@发布组 …] >> S<季>E<集> 单集对照
S<来源季> [@发布组 …] >> 特别篇 | 花絮 | 忽略 整季另作处理
- 来源季写
*(或S*)表示任意季;单集对照不写季(E05 >> S00E02)同样是任意季。 - 目标季可省,省略 = 来源季;只写目标季(
S02 >> S01)= 集号不变。 - 集号表达式与全局识别词同一套算术,
EP不分大小写,必须出现EP;EP单独写 = 集号不变。打印时规范成大写、去空格(ep - 12→EP-12)。 - 发布组前面加
@,可以写多个;带空格的写成@"Some Group"。比较时不分大小写,繁简写法算同一个(綠茶字幕組=绿茶字幕组)。 - 单集对照可以多行,同一范围合成一张对照表,区间不能重叠;区间里每一集都要在表里,目标要在同一季且连续。
- 同一范围(季 + 发布组)只能有一行换算或整季处理;一行多个发布组拆成多条规则。冲突、写错都按行号报出来,有错不能保存。
药屋少女的呢喃(TMDB 只有一季,后面的季接着编号):
# 药屋少女的呢喃:TMDB 只有一季,第二、三季接着第一季编号
S02 >> S01 EP+24
S03 >> S01 EP+48
S03 @ADWeb @MWeb @CHDWEB @黒ネズミたち @Judas @绿茶字幕组 @綠茶字幕組 >> S01 EP
优先级
资源的(来源季, 发布组)找最具体的一条:季 + 发布组 > 只写季 > 只写发布组 > 任意。命中规则就只按它算,算出来对不上季表 → 待确认(不再回退到绝对集号 / 播出日期换算,也不停用这一行);没命中规则才走原号校验与确定性换算。解析结果记命中的行号与原文(episode_resolution.ruleLine / ruleText)。
保存与试算
编辑后自动试算(纯读,POST /media-entities/{id}/identify-words/dry-run):逐行错误、近期 100 条资源换算前后、仍对不上季表的条数。保存(PUT /media-entities/{id}/identify-words)在同一事务里按作品重算已绑定资源,返回重算 / 变化 / 待确认转已解决的条数。
集数待确认事项的「采用建议」「忽略并写忽略规则」、智能体的 episode_mapping.apply_rule 都是往作品识别词末尾追加一行,上方加一行注释写来历(日期、智能体会话、理由)。识别词里有同范围被注释掉的行(用户停用过)时智能体不再自动写。
编辑器
components/identify-words/words-editor.tsx,规则页「识别词」的全局区块、作品抽屉(?open=<作品 id>)和作品页「集数映射」用的是同一个组件:
- 「可视化 / 文本」两种模式改同一份原文,随时切换不丢内容,上次用的模式记在本机。
- 文本模式:等宽、行号、按语法着色,写错的行行号标红、整行浅红底;粘贴 MP 列表就是普通粘贴。
- 可视化模式:一行规则一张卡。先选类型(全局:屏蔽词 / 替换 / 集数偏移 / 替换 + 偏移 / 指定作品;作品:季集换算 / 单集对照 / 特别篇·花絮·忽略),字段按类型展开;集号换算有「不变 / +N / −N / 自定义表达式」;发布组是标签输入,提示这部作品资源里出现过的发布组。开关 = 注释掉与否,拖动(或焦点在手柄上按上下方向键)排序,备注写成上方的注释行,卡片下面拿近期资源(或自己给的标题)试这一行。
- 可视化表达不了的行(写错的)显示成只读的「原文」行,带错误和「在文本里改」,不会丢。
- 行模型
wordsToRows/rowsToText(contracts):紧贴规则上方、没有空行隔开的注释是它的备注;注释内容本身是一条规则的(全局里只认带运算符的)是停用的规则行;没改过的行原样拼回,往返逐字不变。