fix(merge): 中文数字季号正则支持超过十的数字 (#357)

RegexStore.Season.CN 字符类缺少 + 量词,导致 第十三季
等超过十的中文季号只匹配首字 十,与 第十五季 等一同
被误规范为 第10季,引发错误合并。

正则追加 + 量词支持多字符中文数字,
cnNums 查表替换为 convertChineseNumber 处理任意长度。
This commit is contained in:
Elegy233 authored and GitHub committed 2026-07-04 22:03:07 +08:00
1 parent 6a90bc015b
commit 6c236dcb71
1 file changed
+5 -7
+5 -7
View File
@@ -2,7 +2,7 @@ import { globals } from '../configs/globals.js';
import { log as baseLog } from './log-util.js';
import { addAnime } from './cache-util.js';
import { simplized } from '../utils/zh-util.js';
import { normalizeSpaces } from '../utils/common-util.js';
import { normalizeSpaces, convertChineseNumber } from '../utils/common-util.js';
// ==============================================================================
// 源合并处理工具 (merge-util.js)
@@ -139,7 +139,7 @@ const RegexStore = {
PART_NORM_2: /(?:Part|P)[\s.]*(\d+)/gi,
FINAL: /(?:The\s+)?Final\s+Season/gi,
NORM: /(?:Season|S)\s*(\d+)/gi,
CN: /第\s*([一二三四五六七八九十])\s*季/g,
CN: /第\s*([一二三四五六七八九十]+)\s*季/g,
ROMAN: /(\s|^)(IV|III|II|I)(\s|$)/g,
INFO_STRONG: /(?:season|s|第)\s*[0-9一二三四五六七八九十]+\s*(?:季|期|部(?!分))?/gi,
PART_INFO_STRONG: /(?:part|p|第)\s*\d+\s*(?:部分)?/gi,
@@ -377,8 +377,7 @@ function cleanText(text) {
clean = clean.replace(RegexStore.Season.FINAL, '最终季');
clean = clean.replace(RegexStore.Season.NORM, '第$1季');
// 中文数字季度转阿拉伯数字
const cnNums = { '一':'1','二':'2','三':'3','四':'4','五':'5','六':'6','七':'7','八':'8','九':'9','十':'10' };
clean = clean.replace(RegexStore.Season.CN, (m, num) => `第${cnNums[num]}季`);
clean = clean.replace(RegexStore.Season.CN, (m, num) => `第${convertChineseNumber(num)}季`);
// 罗马数字季度转阿拉伯数字
clean = clean.replace(RegexStore.Season.ROMAN, (match, p1, roman, p2) => {
const rMap = { 'I':'1','II':'2','III':'3','IV':'4' };
@@ -1142,7 +1141,7 @@ function identifyRedundantTitle(links, seriesTitle, sourceName) {
try {
let regex = _redundantTitleRegexCache.get(sourceName);
if (!regex) {
const escapedSource = sourceName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const escapedSource = escapeRegExp(sourceName);
regex = new RegExp(`(\\[|【|\\s)?${escapedSource}(\\]|】|\\s)?`, 'gi');
_redundantTitleRegexCache.set(sourceName, regex);
}
@@ -2113,7 +2112,6 @@ function detectCollectionCandidates(curAnimes) {
const collectionIds = new Set();
if (!curAnimes || curAnimes.length === 0) return collectionIds;
const cnNums = {'一':'1','二':'2','三':'3','四':'4','五':'5','六':'6','七':'7','八':'8','九':'9','十':'10'};
const groups = new Map();
curAnimes.forEach(anime => {
@@ -2131,7 +2129,7 @@ function detectCollectionCandidates(curAnimes) {
protectedTitle = protectedTitle.replace(startBracketMatch[0], content + ' ');
}
}
protectedTitle = protectedTitle.replace(/第([一二三四五六七八九十])季/g, (m, num) => `第${cnNums[num]}季`);
protectedTitle = protectedTitle.replace(/第([一二三四五六七八九十]+)季/g, (m, num) => `第${convertChineseNumber(num)}季`);
// 去除所有元数据,只保留核心标题用作分组 key
let clean = protectedTitle