Skip to content

Commit b794f02

Browse files
authored
feat: 完善视频源类型识别逻辑,修复动漫误判为电视剧的问题 (huangxd-#77)
1 parent 90de8a2 commit b794f02

File tree

4 files changed

+137
-17
lines changed

4 files changed

+137
-17
lines changed

danmu_api/sources/bilibili.js

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,8 @@ export default class BilibiliSource extends BaseSource {
169169
const mediaId = item.season_id ? `ss${item.season_id}` : item.bvid ? `bv${item.bvid}` : "";
170170
if (!mediaId) continue;
171171

172-
const mediaType = item.season_type_name === "电影" ? "电影" : "电视剧";
172+
// 提取媒体类型(参考 bilibili.py 和优化后的 youku.js)
173+
const mediaType = this._extractMediaType(item.season_type_name);
173174
const episodeCount = mediaType === "电影" ? 1 : (item.ep_size || 0);
174175

175176
// 提取年份
@@ -217,6 +218,46 @@ export default class BilibiliSource extends BaseSource {
217218
}
218219
}
219220

221+
/**
222+
* 从 season_type_name 提取媒体类型
223+
* B站 API 返回的类型包括:电影、番剧、国创、纪录片、综艺、电视剧等
224+
* @param {string} seasonTypeName - API 返回的 season_type_name
225+
* @returns {string} 标准化的媒体类型
226+
*/
227+
_extractMediaType(seasonTypeName) {
228+
const typeName = (seasonTypeName || "").toLowerCase();
229+
230+
// 电影类型
231+
if (typeName.includes("电影") || typeName.includes("movie")) {
232+
return "电影";
233+
}
234+
235+
// 动漫类型(包括番剧和国创)
236+
if (typeName.includes("番剧") || typeName.includes("国创") ||
237+
typeName.includes("动漫") || typeName.includes("anime")) {
238+
return "动漫";
239+
}
240+
241+
// 纪录片类型
242+
if (typeName.includes("纪录片") || typeName.includes("documentary")) {
243+
return "纪录片";
244+
}
245+
246+
// 综艺类型
247+
if (typeName.includes("综艺") || typeName.includes("variety")) {
248+
return "综艺";
249+
}
250+
251+
// 电视剧类型
252+
if (typeName.includes("电视剧") || typeName.includes("剧集") ||
253+
typeName.includes("drama") || typeName.includes("tv")) {
254+
return "电视剧";
255+
}
256+
257+
// 默认返回电视剧(最常见的类型)
258+
return "电视剧";
259+
}
260+
220261
async search(keyword) {
221262
try {
222263
log("info", `[Bilibili] 开始搜索: ${keyword}`);

danmu_api/sources/iqiyi.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,15 +140,22 @@ export default class IqiyiSource extends BaseSource {
140140
return null;
141141
}
142142

143-
// 过滤不相关频道
143+
// 提取媒体类型(参考优化后的 youku.js 和 bilibili.js)
144144
const channel = album.channel || "";
145-
let mediaType = "电视剧";
145+
let mediaType = "电视剧"; // 默认类型
146+
146147
if (channel.includes("电影")) {
147148
mediaType = "电影";
148-
} else if (channel.includes("电视剧") || channel.includes("动漫")) {
149+
} else if (channel.includes("动漫")) {
150+
mediaType = "动漫";
151+
} else if (channel.includes("综艺")) {
152+
mediaType = "综艺";
153+
} else if (channel.includes("纪录片")) {
154+
mediaType = "纪录片";
155+
} else if (channel.includes("电视剧")) {
149156
mediaType = "电视剧";
150157
} else {
151-
// 只保留电影、电视剧、动漫
158+
// 只保留支持的类型:电影、电视剧、动漫、综艺、纪录片
152159
return null;
153160
}
154161

danmu_api/sources/mango.js

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,43 @@ export default class MangoSource extends BaseSource {
4040
return Math.floor((leftColor + rightColor) / 2);
4141
}
4242

43+
/**
44+
* 从类型字符串中提取标准化的媒体类型
45+
* @param {string} typeStr - API 返回的类型字符串
46+
* @returns {string} 标准化的媒体类型
47+
*/
48+
_extractMediaType(typeStr) {
49+
const type = (typeStr || "").toLowerCase();
50+
51+
// 电影类型
52+
if (type.includes("电影") || type.includes("movie")) {
53+
return "电影";
54+
}
55+
56+
// 动漫类型
57+
if (type.includes("动漫") || type.includes("动画") || type.includes("anime")) {
58+
return "动漫";
59+
}
60+
61+
// 综艺类型
62+
if (type.includes("综艺") || type.includes("真人秀") || type.includes("variety")) {
63+
return "综艺";
64+
}
65+
66+
// 纪录片类型
67+
if (type.includes("纪录片") || type.includes("documentary")) {
68+
return "纪录片";
69+
}
70+
71+
// 电视剧类型
72+
if (type.includes("电视剧") || type.includes("剧集") || type.includes("drama") || type.includes("tv")) {
73+
return "电视剧";
74+
}
75+
76+
// 默认返回电视剧(最常见的类型)
77+
return "电视剧";
78+
}
79+
4380
async search(keyword) {
4481
try {
4582
log("info", `[Mango] 开始搜索: ${keyword}`);
@@ -95,9 +132,9 @@ export default class MangoSource extends BaseSource {
95132
const yearMatch = item.desc && item.desc[0] ? item.desc[0].match(/[12][890][0-9][0-9]/) : null;
96133
const year = yearMatch ? parseInt(yearMatch[0]) : null;
97134

98-
// 提取类型
135+
// 提取媒体类型(参考优化后的 youku.js 和 bilibili.js)
99136
const typeMatch = item.desc && item.desc[0] ? item.desc[0].split('/')[0].replace("类型:", "").trim() : '';
100-
const mediaType = typeMatch === "电影" ? "电影" : "电视剧";
137+
const mediaType = this._extractMediaType(typeMatch);
101138

102139
results.push({
103140
provider: "imgo",

danmu_api/sources/youku.js

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,31 @@ export default class YoukuSource extends BaseSource {
5555
// 清理标题 (移除HTML标签和特殊符号)
5656
let cleanedTitle = title.replace(/<[^>]+>/g, '').replace(/.+?/g, '').trim().replace(/:/g, ':');
5757

58-
// 提取媒体类型
59-
const mediaType = commonData.feature.includes("电影") ? "电影" : "电视剧";
58+
// 提取媒体类型(参考 Python 版本的 _extract_media_type_from_response)
59+
let mediaType = "电视剧"; // 默认类型
60+
const cats = (commonData.cats || "").toLowerCase();
61+
const feature = (commonData.feature || "").toLowerCase();
62+
63+
// 优先使用 cats 字段
64+
if (cats.includes("动漫") || cats.includes("anime")) {
65+
mediaType = "动漫";
66+
} else if (cats.includes("电影") || cats.includes("movie")) {
67+
mediaType = "电影";
68+
} else if (cats.includes("电视剧") || cats.includes("drama")) {
69+
mediaType = "电视剧";
70+
} else if (cats.includes("综艺") || cats.includes("variety")) {
71+
mediaType = "综艺";
72+
}
73+
// 备用:从 feature 字段提取
74+
else if (feature.includes("动漫")) {
75+
mediaType = "动漫";
76+
} else if (feature.includes("电影")) {
77+
mediaType = "电影";
78+
} else if (feature.includes("电视剧")) {
79+
mediaType = "电视剧";
80+
} else if (feature.includes("综艺")) {
81+
mediaType = "综艺";
82+
}
6083

6184
return {
6285
provider: "youku",
@@ -323,27 +346,39 @@ export default class YoukuSource extends BaseSource {
323346
}
324347

325348
/**
326-
* 从分类信息中提取媒体类型
349+
* 从分类信息中提取媒体类型(参考 Python 版本的 _extract_media_type_from_response)
327350
* @param {string} cats - 分类字符串
328351
* @param {string} feature - 特征字符串
329-
* @returns {string} 媒体类型
352+
* @returns {string} 媒体类型 (variety/movie/anime/drama)
330353
*/
331354
_extractMediaType(cats, feature) {
332355
const catsLower = (cats || '').toLowerCase();
333356
const featureLower = (feature || '').toLowerCase();
334357

335-
if (catsLower.includes('综艺') || catsLower.includes('variety') || featureLower.includes('综艺')) {
358+
// 优先使用 cats 字段
359+
if (catsLower.includes('综艺') || catsLower.includes('variety')) {
360+
return 'variety';
361+
} else if (catsLower.includes('电影') || catsLower.includes('movie')) {
362+
return 'movie';
363+
} else if (catsLower.includes('动漫') || catsLower.includes('anime')) {
364+
return 'anime';
365+
} else if (catsLower.includes('电视剧') || catsLower.includes('drama')) {
366+
return 'drama';
367+
}
368+
369+
// 备用:从 feature 字段提取
370+
if (featureLower.includes('综艺')) {
336371
return 'variety';
337-
} else if (catsLower.includes('电影') || catsLower.includes('movie') || featureLower.includes('电影')) {
372+
} else if (featureLower.includes('电影')) {
338373
return 'movie';
339-
} else if (catsLower.includes('动漫') || catsLower.includes('anime') || featureLower.includes('动漫')) {
374+
} else if (featureLower.includes('动漫')) {
340375
return 'anime';
341-
} else if (catsLower.includes('电视剧') || catsLower.includes('drama') || featureLower.includes('电视剧')) {
376+
} else if (featureLower.includes('电视剧')) {
342377
return 'drama';
343378
}
344379

345-
// 默认返回综艺
346-
return 'variety';
380+
// 默认返回电视剧类型
381+
return 'drama';
347382
}
348383

349384
async getEpisodeDanmu(id) {

0 commit comments

Comments
 (0)