mirror of
https://github.com/Cp0204/quark-auto-save.git
synced 2026-01-14 08:20:42 +08:00
优化资源搜索和谷歌搜索的逻辑,智能填充增加对中文季数的支持
1. 使用去除季数的任务名称进行搜索,获取更完整的搜索结果 2. 支持解析中文季序号,用于在智能填充时自动识别季序号
This commit is contained in:
parent
7aae96a63e
commit
c2425392a6
53
app/run.py
53
app/run.py
@ -263,6 +263,40 @@ def get_task_suggestions():
|
||||
return jsonify({"success": False, "message": "未登录"})
|
||||
query = request.args.get("q", "").lower()
|
||||
deep = request.args.get("d", "").lower()
|
||||
|
||||
# 提取剧名,去除季数信息
|
||||
def extract_show_name(task_name):
|
||||
# 清理任务名称中的连续空格和特殊符号
|
||||
clean_name = task_name.replace('\u3000', ' ').replace('\t', ' ')
|
||||
clean_name = re.sub(r'\s+', ' ', clean_name).strip()
|
||||
|
||||
# 匹配常见的季数格式
|
||||
# 例如:黑镜 - S07、人生若如初见 - S01、折腰.S01、音你而来-S02、快乐的大人 S02
|
||||
season_patterns = [
|
||||
r'^(.*?)[\s\.\-_]+S\d+$', # 黑镜 - S07、折腰.S01、音你而来-S02
|
||||
r'^(.*?)[\s\.\-_]+Season\s*\d+$', # 黑镜 - Season 1
|
||||
r'^(.*?)\s+S\d+$', # 快乐的大人 S02
|
||||
r'^(.*?)[\s\.\-_]+S\d+E\d+$', # 处理 S01E01 格式
|
||||
r'^(.*?)\s+第\s*\d+\s*季$', # 处理 第N季 格式
|
||||
r'^(.*?)[\s\.\-_]+第\s*\d+\s*季$', # 处理 - 第N季 格式
|
||||
r'^(.*?)\s+第[一二三四五六七八九十零]+季$', # 处理 第一季、第二季 格式
|
||||
r'^(.*?)[\s\.\-_]+第[一二三四五六七八九十零]+季$', # 处理 - 第一季、- 第二季 格式
|
||||
]
|
||||
|
||||
for pattern in season_patterns:
|
||||
match = re.match(pattern, clean_name, re.IGNORECASE)
|
||||
if match:
|
||||
show_name = match.group(1).strip()
|
||||
# 去除末尾可能残留的分隔符
|
||||
show_name = re.sub(r'[\s\.\-_]+$', '', show_name)
|
||||
return show_name
|
||||
|
||||
# 如果没有匹配到季数格式,返回原名称
|
||||
return clean_name
|
||||
|
||||
# 处理搜索关键词,提取剧名
|
||||
search_query = extract_show_name(query)
|
||||
|
||||
try:
|
||||
cs_data = config_data.get("source", {}).get("cloudsaver", {})
|
||||
if (
|
||||
@ -276,23 +310,34 @@ def get_task_suggestions():
|
||||
cs_data.get("password", ""),
|
||||
cs_data.get("token", ""),
|
||||
)
|
||||
search = cs.auto_login_search(query)
|
||||
# 使用处理后的搜索关键词
|
||||
search = cs.auto_login_search(search_query)
|
||||
if search.get("success"):
|
||||
if search.get("new_token"):
|
||||
cs_data["token"] = search.get("new_token")
|
||||
Config.write_json(CONFIG_PATH, config_data)
|
||||
search_results = cs.clean_search_results(search.get("data"))
|
||||
# 在返回结果中添加实际使用的搜索关键词
|
||||
return jsonify(
|
||||
{"success": True, "source": "CloudSaver", "data": search_results}
|
||||
{
|
||||
"success": True,
|
||||
"source": "CloudSaver",
|
||||
"data": search_results
|
||||
}
|
||||
)
|
||||
else:
|
||||
return jsonify({"success": True, "message": search.get("message")})
|
||||
else:
|
||||
base_url = base64.b64decode("aHR0cHM6Ly9zLjkxNzc4OC54eXo=").decode()
|
||||
url = f"{base_url}/task_suggestions?q={query}&d={deep}"
|
||||
# 使用处理后的搜索关键词
|
||||
url = f"{base_url}/task_suggestions?q={search_query}&d={deep}"
|
||||
response = requests.get(url)
|
||||
return jsonify(
|
||||
{"success": True, "source": "网络公开", "data": response.json()}
|
||||
{
|
||||
"success": True,
|
||||
"source": "网络公开",
|
||||
"data": response.json()
|
||||
}
|
||||
)
|
||||
except Exception as e:
|
||||
return jsonify({"success": True, "message": f"error: {str(e)}"})
|
||||
|
||||
@ -483,7 +483,9 @@
|
||||
</span>
|
||||
<span v-else>正在搜索中...</span>
|
||||
</div>
|
||||
<div class="dropdown-item text-muted" v-else style="font-size:14px; padding-left: 8px; text-align: left;">{{ smart_param.taskSuggestions.message ? smart_param.taskSuggestions.message : smart_param.taskSuggestions.data && smart_param.taskSuggestions.data.length ? `以下资源由 ${smart_param.taskSuggestions.source} 搜索提供(仅显示有效链接),如有侵权请联系资源发布方` : "未搜索到有效资源" }}</div>
|
||||
<div class="dropdown-item text-muted" v-else style="font-size:14px; padding-left: 8px; text-align: left;">
|
||||
{{ smart_param.taskSuggestions.message ? smart_param.taskSuggestions.message : smart_param.taskSuggestions.data && smart_param.taskSuggestions.data.length ? `以下资源由 ${smart_param.taskSuggestions.source} 搜索提供(仅显示有效链接),如有侵权请联系资源发布方` : "未搜索到有效资源" }}
|
||||
</div>
|
||||
<div v-for="suggestion in smart_param.taskSuggestions.data || []" :key="suggestion.taskname" class="dropdown-item cursor-pointer" @click.prevent="selectSuggestion(index, suggestion)" style="font-size: 14px;" :title="suggestion.content">
|
||||
<span v-html="suggestion.verify ? '✅': ''"></span> {{ suggestion.taskname }}
|
||||
<small class="text-muted">
|
||||
@ -497,7 +499,7 @@
|
||||
<i v-else class="bi bi-search"></i>
|
||||
</button>
|
||||
<div class="input-group-text" title="谷歌搜索">
|
||||
<a target="_blank" :href="`https://www.google.com/search?q=%22pan.quark.cn/s%22+${task.taskname}`"><i class="bi bi-google"></i></a>
|
||||
<a target="_blank" :href="`https://www.google.com/search?q=%22pan.quark.cn/s%22+${cleanTaskNameForSearch(task.taskname)}`"><i class="bi bi-google"></i></a>
|
||||
</div>
|
||||
<div class="input-group-text" title="TMDB搜索">
|
||||
<a target="_blank" :href="`https://www.themoviedb.org/search?query=${cleanTaskNameForSearch(task.taskname)}`"><img src="./static/TMDB.svg" class="tmdb-icon"></a>
|
||||
@ -1340,12 +1342,39 @@
|
||||
},
|
||||
cleanTaskNameForSearch(taskName) {
|
||||
if (!taskName) return '';
|
||||
// 移除 Sxx 格式(包括 S01、S01E01 等)
|
||||
let cleanedName = taskName.replace(/\s*[-–—_]\s*S\d+(\w\d+)?/i, '');
|
||||
|
||||
// 清理任务名称中的连续空格和特殊符号
|
||||
let cleanedName = taskName.replace(/\u3000/g, ' ').replace(/\t/g, ' ');
|
||||
cleanedName = cleanedName.replace(/\s+/g, ' ').trim();
|
||||
|
||||
// 匹配常见的季数格式
|
||||
const seasonPatterns = [
|
||||
/^(.*?)[\s\.\-_]+S\d+$/i, // 黑镜 - S07、折腰.S01、音你而来-S02
|
||||
/^(.*?)[\s\.\-_]+Season\s*\d+$/i, // 黑镜 - Season 1
|
||||
/^(.*?)\s+S\d+$/i, // 快乐的大人 S02
|
||||
/^(.*?)[\s\.\-_]+S\d+E\d+$/i, // 处理 S01E01 格式
|
||||
/^(.*?)\s+第\s*\d+\s*季$/i, // 处理 第N季 格式
|
||||
/^(.*?)[\s\.\-_]+第\s*\d+\s*季$/i, // 处理 - 第N季 格式
|
||||
/^(.*?)\s+第[一二三四五六七八九十零]+季$/i, // 处理 第一季、第二季 格式
|
||||
/^(.*?)[\s\.\-_]+第[一二三四五六七八九十零]+季$/i, // 处理 - 第一季、- 第二季 格式
|
||||
];
|
||||
|
||||
for (const pattern of seasonPatterns) {
|
||||
const match = cleanedName.match(pattern);
|
||||
if (match) {
|
||||
let showName = match[1].trim();
|
||||
// 去除末尾可能残留的分隔符
|
||||
showName = showName.replace(/[\s\.\-_]+$/, '');
|
||||
return encodeURIComponent(showName);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有匹配到季数格式,执行原有的清理逻辑
|
||||
// 移除孤立的特殊符号
|
||||
cleanedName = cleanedName.replace(/\s*[-–—_]\s*$/, '');
|
||||
// 移除开头和结尾的特殊符号
|
||||
cleanedName = cleanedName.trim().replace(/^[-–—_\s]+|[-–—_\s]+$/g, '');
|
||||
|
||||
return encodeURIComponent(cleanedName);
|
||||
},
|
||||
changeTab(tab) {
|
||||
@ -1593,10 +1622,42 @@
|
||||
const cleanTaskName = task.taskname.replace(/\s+/g, ' ').trim();
|
||||
|
||||
// 提取任务名称中的分隔符格式
|
||||
// 检测任务名称中剧名和季序号之间的分隔符
|
||||
const separatorMatch = cleanTaskName.match(/^(.*?)([\s\.\-_]+)(?:S(\d+)|Season\s*(\d+))/i);
|
||||
// 使用与cleanTaskNameForSearch相同的季数格式匹配模式
|
||||
let showName, seasonNumber, nameSeparator = ' - '; // 默认分隔符
|
||||
let isTVShow = false; // 标记是否为电视节目
|
||||
let separatorMatch = null;
|
||||
|
||||
// 匹配常见的季数格式
|
||||
const seasonPatterns = [
|
||||
/^(.*?)([\s\.\-_]+)S(\d+)$/i, // 黑镜 - S07、折腰.S01、音你而来-S02
|
||||
/^(.*?)([\s\.\-_]+)Season\s*(\d+)$/i, // 黑镜 - Season 1
|
||||
/^(.*?)(\s+)S(\d+)$/i, // 快乐的大人 S02
|
||||
/^(.*?)([\s\.\-_]+)S(\d+)E\d+$/i, // 处理 S01E01 格式
|
||||
/^(.*?)(\s+)第\s*(\d+)\s*季$/i, // 处理 第N季 格式
|
||||
/^(.*?)([\s\.\-_]+)第\s*(\d+)\s*季$/i, // 处理 - 第N季 格式
|
||||
/^(.*?)(\s+)第([一二三四五六七八九十零]+)季$/i, // 处理 第一季、第二季 格式
|
||||
/^(.*?)([\s\.\-_]+)第([一二三四五六七八九十零]+)季$/i, // 处理 - 第一季、- 第二季 格式
|
||||
];
|
||||
|
||||
// 尝试匹配各种格式
|
||||
for (const pattern of seasonPatterns) {
|
||||
const match = cleanTaskName.match(pattern);
|
||||
if (match) {
|
||||
separatorMatch = match;
|
||||
// 根据不同的格式,确定季序号的位置
|
||||
if (match[3] && match[3].match(/[一二三四五六七八九十零]/)) {
|
||||
// 将中文数字转换为阿拉伯数字
|
||||
const chineseToNumber = {
|
||||
'零': '0', '一': '1', '二': '2', '三': '3', '四': '4',
|
||||
'五': '5', '六': '6', '七': '7', '八': '8', '九': '9', '十': '10'
|
||||
};
|
||||
seasonNumber = chineseToNumber[match[3]] || '01';
|
||||
} else {
|
||||
seasonNumber = match[3] || '01';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 判断保存路径是否包含电视节目相关的关键词
|
||||
if (task.savepath) {
|
||||
@ -1605,25 +1666,34 @@
|
||||
}
|
||||
|
||||
// 当任务名称包含季信息或保存路径有电视剧关键词时,按电视节目处理
|
||||
const hasSeason = separatorMatch && (separatorMatch[3] || separatorMatch[4]);
|
||||
const hasSeason = separatorMatch !== null;
|
||||
isTVShow = isTVShow || hasSeason;
|
||||
|
||||
if (separatorMatch) {
|
||||
// 提取剧名(去除末尾空格和特殊符号)
|
||||
showName = separatorMatch[1].trim().replace(/[\s\.\-_]+$/, '');
|
||||
// 提取季序号
|
||||
seasonNumber = separatorMatch[3] || separatorMatch[4] || '01';
|
||||
// 季序号已在上面的循环中提取
|
||||
// 提取实际使用的分隔符
|
||||
const rawSeparator = separatorMatch[2];
|
||||
// 规范化分隔符(如果是连续的空格,转为单个空格)
|
||||
nameSeparator = rawSeparator.replace(/\s+/g, ' ');
|
||||
// 如果只有一个点号,保留点号
|
||||
if (rawSeparator === '.') {
|
||||
nameSeparator = '.';
|
||||
}
|
||||
// 如果是单个空格,保留单个空格
|
||||
else if (rawSeparator === ' ') {
|
||||
nameSeparator = ' ';
|
||||
|
||||
// 处理特殊情况:如果是"黑镜 - 第五季"这种格式,需要保留完整的" - "分隔符
|
||||
// 检查原始字符串中剧名后面的分隔符
|
||||
const fullSeparator = cleanTaskName.substring(showName.length, cleanTaskName.length - (separatorMatch[3] ? separatorMatch[3].length + 1 : 0)).match(/^([\s\.\-_]+)/);
|
||||
|
||||
if (fullSeparator && fullSeparator[1]) {
|
||||
// 使用完整的分隔符
|
||||
nameSeparator = fullSeparator[1];
|
||||
} else {
|
||||
// 规范化分隔符(如果是连续的空格,转为单个空格)
|
||||
nameSeparator = rawSeparator.replace(/\s+/g, ' ');
|
||||
// 如果只有一个点号,保留点号
|
||||
if (rawSeparator === '.') {
|
||||
nameSeparator = '.';
|
||||
}
|
||||
// 如果是单个空格,保留单个空格
|
||||
else if (rawSeparator === ' ') {
|
||||
nameSeparator = ' ';
|
||||
}
|
||||
}
|
||||
// 其他情况保持原样
|
||||
} else {
|
||||
@ -1672,6 +1742,44 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 额外处理:检查保存路径最末级是否包含中文季序号,如果包含则转换为标准格式
|
||||
if (task.savepath) {
|
||||
const pathParts = task.savepath.split('/');
|
||||
if (pathParts.length > 0) {
|
||||
const lastPart = pathParts[pathParts.length - 1];
|
||||
// 匹配中文季序号格式
|
||||
const chineseSeasonMatch = lastPart.match(/^(.*?)([\s\.\-_]+)第([一二三四五六七八九十零]+)季$/);
|
||||
if (chineseSeasonMatch) {
|
||||
const showName = chineseSeasonMatch[1].trim();
|
||||
const separator = chineseSeasonMatch[2];
|
||||
const chineseSeason = chineseSeasonMatch[3];
|
||||
|
||||
// 将中文数字转换为阿拉伯数字
|
||||
const chineseToNumber = {
|
||||
'零': '0', '一': '1', '二': '2', '三': '3', '四': '4',
|
||||
'五': '5', '六': '6', '七': '7', '八': '8', '九': '9', '十': '10'
|
||||
};
|
||||
const seasonNumber = chineseToNumber[chineseSeason] || '1';
|
||||
|
||||
// 更新最末级目录为标准格式
|
||||
pathParts[pathParts.length - 1] = showName + separator + 'S' + seasonNumber.padStart(2, '0');
|
||||
task.savepath = pathParts.join('/');
|
||||
}
|
||||
|
||||
// 匹配阿拉伯数字季序号格式
|
||||
const arabicSeasonMatch = lastPart.match(/^(.*?)([\s\.\-_]+)第(\d+)季$/);
|
||||
if (arabicSeasonMatch) {
|
||||
const showName = arabicSeasonMatch[1].trim();
|
||||
const separator = arabicSeasonMatch[2];
|
||||
const seasonNumber = arabicSeasonMatch[3];
|
||||
|
||||
// 更新最末级目录为标准格式
|
||||
pathParts[pathParts.length - 1] = showName + separator + 'S' + seasonNumber.padStart(2, '0');
|
||||
task.savepath = pathParts.join('/');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新命名规则 - 始终使用当前任务名称中的信息
|
||||
if (task.pattern) {
|
||||
// 根据是否为电视节目决定处理方式
|
||||
|
||||
Loading…
Reference in New Issue
Block a user