Skip to content

Commit 8e3d208

Browse files
authored
大幅优化 Bangumi Data 检索性能与速度,避免中低端机器开启为负优化 (huangxd-#301)
* bangumi-data-util.js:大幅优化数据查询性能 * tmdb-util.js:异步查询本地 Bangumi Data * animeko.js:异步查询本地 Bangumi Data * bahamut.js:异步查询本地 Bangumi Data * bilibili.js:异步查询本地 Bangumi Data * dandan.js:异步查询本地 Bangumi Data * bangumi-data-util.js:兼容旧版数据缓存 * tmdb-util.js:调整日志输出 * renren.js:捕获空弹幕数据,直接返回空数组 * renren.js:还原修改,因为并不有效 Removed checks for 'Document not found' error in response handling. * merge-util.js:再次修复Re0最新季因共识差导致animeko映射错误 * bangumi-data-util.js:再次优化,引入倒排索引避免未来数据越来越多检索变慢 * dandan.js:如果结果命中用户需要的季,则跳过非目标季相关请求 减轻容易报错的详情接口压力 * merge-util.js:只有 1 个资源时不进行合并计算 * bahamut.js:如果结果命中用户需要的季,则跳过非目标季相关请求 * Add extractSeasonNumberFromAnimeTitle to imports * Add extractSeasonNumberFromAnimeTitle to imports * Add extractSeasonNumberFromAnimeTitle to imports * bilibili.js:更新 Bangumi Data 数据对齐匹配逻辑,修复中配版对齐错误 * bahamut.js:同步更新 Bangumi Data 数据对齐匹配逻辑 * bahamut.js:补全 Bangumi Data 数据对齐标识,修复对齐后TMDB标题替换错误启动 * tmdb-util.js:调整智能标题替换执行逻辑,无有效资源时不再进行无效计算
1 parent a51fb8d commit 8e3d208

7 files changed

Lines changed: 401 additions & 129 deletions

File tree

danmu_api/sources/animeko.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ export default class AnimekoSource extends BaseSource {
3737
*/
3838
async search(keyword) {
3939
if (globals.useBangumiData) {
40-
const localMatches = searchBangumiData(keyword, ['bangumi']);
40+
const localMatches = await searchBangumiData(keyword, ['bangumi']);
4141
if (localMatches.length > 0) {
42-
log("info", `[Animeko] Bangumi-Data 命中 ${localMatches.length} 条数据`);
42+
log("info", `[Animeko] Bangumi-Data 本地命中 ${localMatches.length} 条数据`);
4343
return this.transformResults(localMatches.map(m => {
4444
const displayTitle = m.titles.find(t => t && t.includes(keyword)) || m.titles[1] || m.title;
4545
const finalTitle = displayTitle + (m.titleSuffix || '');

danmu_api/sources/bahamut.js

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { generateValidStartDate } from "../utils/time-util.js";
66
import { addAnime, removeEarliestAnime } from "../utils/cache-util.js";
77
import { simplized, traditionalized } from "../utils/zh-util.js";
88
import { getTmdbJaOriginalTitle, smartTitleReplace } from "../utils/tmdb-util.js";
9-
import { strictTitleMatch, normalizeSpaces } from "../utils/common-util.js";
9+
import { strictTitleMatch, normalizeSpaces, getExplicitSeasonNumber, extractSeasonNumberFromAnimeTitle } from "../utils/common-util.js";
1010
import { SegmentListResponse } from '../models/dandan-model.js';
1111
import { searchBangumiData } from '../utils/bangumi-data-util.js';
1212

@@ -21,7 +21,7 @@ export default class BahamutSource extends BaseSource {
2121
let localMatches = [];
2222
// 提前获取本地匹配结果
2323
if (globals.useBangumiData) {
24-
localMatches = searchBangumiData(keyword, ['gamer', 'gamer_hk']);
24+
localMatches = await searchBangumiData(keyword, ['gamer', 'gamer_hk']);
2525
log("info", `[Bahamut] Bangumi-Data 本地命中 ${localMatches.length} 条数据`);
2626
}
2727

@@ -161,11 +161,10 @@ export default class BahamutSource extends BaseSource {
161161
for (const item of finalResults) {
162162
if (!item || !item.acg_sn) continue;
163163

164-
// 依据 acg_sn 匹配本地数据
165-
const matchedLocal = localMatches.find(m =>
166-
String(item.acg_sn) === String(m.siteId) ||
167-
(item.title && m.title === item.title)
168-
);
164+
// 对齐逻辑:优先精准匹配 acg_sn,其次降级匹配原名
165+
const matchedLocal =
166+
localMatches.find(m => String(item.acg_sn) === String(m.siteId)) ||
167+
localMatches.find(m => item.title && m.title === item.title);
169168

170169
if (matchedLocal) {
171170
const originalBahamutTitle = item.title;
@@ -175,6 +174,7 @@ export default class BahamutSource extends BaseSource {
175174
// 注入本地别名和优选标题,同时挂载精准类型
176175
item.title = finalTitle;
177176
item._displayTitle = finalTitle;
177+
item.isLocalPriority = true;
178178
item.aliases = [...matchedLocal.titles];
179179

180180
// 将原始网络标题加入别名池,防止后续匹配时丢失源站的精确特征
@@ -337,8 +337,28 @@ export default class BahamutSource extends BaseSource {
337337
const cnAlias = filtered.length > 0 ? filtered[0]._tmdbCnAlias : null;
338338
smartTitleReplace(filtered, cnAlias);
339339

340+
// 提取搜索词中的明确季度信息
341+
const querySeason = getExplicitSeasonNumber(queryTitle);
342+
343+
// 初始列表预过滤机制:若用户指定了季度,优先检查初始结果中是否已包含匹配项
344+
let matchedAnimes = filtered;
345+
346+
if (querySeason !== null) {
347+
const seasonFiltered = filtered.filter(anime => {
348+
const titleToCheck = anime._displayTitle || anime.title;
349+
const s = extractSeasonNumberFromAnimeTitle(titleToCheck).season;
350+
return s === querySeason || (querySeason === 1 && s === null);
351+
});
352+
353+
// 如果已命中目标,减少详情请求量
354+
if (seasonFiltered.length > 0) {
355+
matchedAnimes = seasonFiltered;
356+
log("info", `[Bahamut] 结果已命中目标季(第${querySeason}季),跳过非目标季相关请求`);
357+
}
358+
}
359+
340360
// 使用 map 和 async 时需要返回 Promise 数组,并等待所有 Promise 完成
341-
const processBahamutAnimes = await Promise.all(filtered.map(async (anime) => {
361+
const processBahamutAnimes = await Promise.all(matchedAnimes.map(async (anime) => {
342362
try {
343363
const epData = await this.getEpisodes(anime.video_sn);
344364
const detail = epData.video;

danmu_api/sources/bilibili.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ export default class BilibiliSource extends BaseSource {
288288
let localMatches = [];
289289
if (globals.useBangumiData) {
290290
// 获取本地匹配条目
291-
localMatches = searchBangumiData(keyword, [
291+
localMatches = await searchBangumiData(keyword, [
292292
'bilibili', 'bilibili_hk_mo_tw', 'bilibili_hk_mo', 'bilibili_tw'
293293
]);
294294
log("info", `[Bilibili] Bangumi-Data 本地命中 ${localMatches.length} 条数据`);
@@ -321,15 +321,14 @@ export default class BilibiliSource extends BaseSource {
321321
const seenIds = new Set();
322322
const consumedLocalMdIds = new Set();
323323

324-
// 处理网络结果:对齐本地数据进行信息增强
324+
// 对齐 Bangumi Data 进行信息强化
325325
for (const item of networkResults) {
326326
if (!item || (!item.mediaId && !item.season_id)) continue;
327327

328-
// 对齐逻辑:优先匹配 mdId,其次匹配原名
329-
const matchedLocal = localMatches.find(m =>
330-
(item.mdId && item.mdId === `md${m.siteId}`) ||
331-
(item.org_title && m.title === item.org_title)
332-
);
328+
// 对齐逻辑:优先精准匹配 mdId,其次降级匹配原名
329+
const matchedLocal =
330+
localMatches.find(m => item.mdId && item.mdId === `md${m.siteId}`) ||
331+
localMatches.find(m => item.org_title && m.title === item.org_title);
333332

334333
if (matchedLocal) {
335334
const displayTitle = matchedLocal.titles.find(t => t && t.includes(keyword)) || matchedLocal.titles[1] || matchedLocal.title;

danmu_api/sources/dandan.js

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import MangoSource from "./mango.js";
1212
import BilibiliSource from "./bilibili.js";
1313
import YoukuSource from "./youku.js";
1414
import BahamutSource from "./bahamut.js";
15-
import { titleMatches, getExplicitSeasonNumber } from "../utils/common-util.js";
15+
import { titleMatches, getExplicitSeasonNumber, extractSeasonNumberFromAnimeTitle } from "../utils/common-util.js";
1616
import { searchBangumiData } from '../utils/bangumi-data-util.js';
1717

1818
const tencentSource = new TencentSource();
@@ -37,7 +37,7 @@ export default class DandanSource extends BaseSource {
3737
*/
3838
async search(keyword, isFallback = false) {
3939
if (globals.useBangumiData && !isFallback) {
40-
const localMatches = searchBangumiData(keyword, ['anidb']);
40+
const localMatches = await searchBangumiData(keyword, ['anidb']);
4141
if (localMatches.length > 0) {
4242
log("info", `[Dandan] Bangumi-Data 本地命中 ${localMatches.length} 条数据`);
4343
return localMatches.map(m => {
@@ -314,8 +314,30 @@ export default class DandanSource extends BaseSource {
314314
const existingIds = new Set();
315315
const queue = [];
316316

317-
// 初始化任务队列与去重池:将所有初始搜索结果载入队列,标记为非相关作品
318-
for (const anime of sourceAnimes) {
317+
// 提取搜索词中的明确季度信息
318+
const querySeason = getExplicitSeasonNumber(queryTitle);
319+
320+
// 初始列表预过滤机制:若用户指定了季度,优先检查初始结果中是否已包含匹配项
321+
let matchedAnimes = sourceAnimes;
322+
let isTargetFoundInInitial = false;
323+
324+
if (querySeason !== null) {
325+
const filtered = sourceAnimes.filter(anime => {
326+
const titleToCheck = anime._displayTitle || anime.animeTitle;
327+
const s = extractSeasonNumberFromAnimeTitle(titleToCheck).season;
328+
return s === querySeason || (querySeason === 1 && s === null);
329+
});
330+
331+
// 如果已命中目标,减少详情请求量
332+
if (filtered.length > 0) {
333+
matchedAnimes = filtered;
334+
isTargetFoundInInitial = true;
335+
log("info", `[Dandan] 结果已命中目标季(第${querySeason}季),跳过非目标季相关请求`);
336+
}
337+
}
338+
339+
// 初始化任务队列与去重池:将筛选后的条目载入队列,标记为非相关作品
340+
for (const anime of matchedAnimes) {
319341
existingIds.add(anime.animeId);
320342
queue.push({ ...anime, isRelated: false });
321343
}
@@ -334,11 +356,14 @@ export default class DandanSource extends BaseSource {
334356
// 计算当前作品标题与用户原始搜索词的相似度
335357
const similarity = this.calculateSimilarity(queryTitle, anime.animeTitle);
336358

359+
// 关联挖掘控制逻辑:仅当用户未指定明确季度,或者初始扫描未命中目标季度时,才执行相关作品的深度展开
360+
const canExpandRelateds = !isTargetFoundInInitial;
361+
337362
// 相似度高于10%时,对每个关联作品单独判断是否符合展开条件:
338363
// 关联作品标题含季度信息(避免范围发散),或初始搜索结果不少于25个(API25个结果上限,用相关作品突破)
339-
if (similarity >= 0.1 && details.relateds && Array.isArray(details.relateds)) {
364+
if (similarity >= 0.1 && details.relateds && Array.isArray(details.relateds) && canExpandRelateds) {
340365
for (const rel of details.relateds) {
341-
const hasSeason = getExplicitSeasonNumber(rel.animeTitle) !== null;
366+
const hasSeason = extractSeasonNumberFromAnimeTitle(rel.animeTitle).season !== null;
342367
if (!existingIds.has(rel.animeId) && (hasSeason || initialCount >= 25)) {
343368
existingIds.add(rel.animeId);
344369
queue.push({

0 commit comments

Comments
 (0)