mirror of
https://github.com/Cp0204/quark-auto-save.git
synced 2026-01-17 09:50:42 +08:00
将顺序命名使用的文件排序函数改为全局函数,并优化排序方式
This commit is contained in:
parent
d6390cde99
commit
649169327b
163
app/run.py
163
app/run.py
@ -31,9 +31,9 @@ sys.path.insert(0, parent_dir)
|
|||||||
from quark_auto_save import Quark
|
from quark_auto_save import Quark
|
||||||
from quark_auto_save import Config
|
from quark_auto_save import Config
|
||||||
|
|
||||||
# 添加导入全局extract_episode_number函数
|
# 添加导入全局extract_episode_number和sort_file_by_name函数
|
||||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
from quark_auto_save import extract_episode_number
|
from quark_auto_save import extract_episode_number, sort_file_by_name
|
||||||
|
|
||||||
|
|
||||||
def get_app_ver():
|
def get_app_ver():
|
||||||
@ -328,157 +328,7 @@ def get_share_detail():
|
|||||||
|
|
||||||
# 实现与实际重命名相同的排序算法
|
# 实现与实际重命名相同的排序算法
|
||||||
def extract_sort_value(file):
|
def extract_sort_value(file):
|
||||||
if file["dir"]: # 跳过文件夹
|
return sort_file_by_name(file)
|
||||||
return float('inf')
|
|
||||||
|
|
||||||
filename = file["file_name"]
|
|
||||||
|
|
||||||
# 提取文件名,不含扩展名
|
|
||||||
file_name_without_ext = os.path.splitext(filename)[0]
|
|
||||||
|
|
||||||
# 1. "第X期/集/话" 格式 - 保持最高优先级
|
|
||||||
match_chinese = re.search(r'第(\d+)[期集话]', filename)
|
|
||||||
episode_num = int(match_chinese.group(1)) if match_chinese else 0
|
|
||||||
|
|
||||||
# 5. 文件名含"上中下"(优先处理,因为可能与其他格式同时存在)
|
|
||||||
if match_chinese:
|
|
||||||
# 如果同时存在集数和上中下,则按照集数*10+位置排序
|
|
||||||
if '上' in filename:
|
|
||||||
return episode_num * 10 + 1
|
|
||||||
elif '中' in filename:
|
|
||||||
return episode_num * 10 + 2
|
|
||||||
elif '下' in filename:
|
|
||||||
return episode_num * 10 + 3
|
|
||||||
return episode_num * 10
|
|
||||||
elif '上' in filename:
|
|
||||||
return 1
|
|
||||||
elif '中' in filename:
|
|
||||||
return 2
|
|
||||||
elif '下' in filename:
|
|
||||||
return 3
|
|
||||||
|
|
||||||
# 1.2 "X集/期/话" 格式 - 与我们修改后的优先级一致
|
|
||||||
match_chinese_simple = re.search(r'(\d+)[期集话]', filename)
|
|
||||||
if match_chinese_simple:
|
|
||||||
return int(match_chinese_simple.group(1))
|
|
||||||
|
|
||||||
# 2.1 S01E01 格式,提取季数和集数
|
|
||||||
match_s_e = re.search(r'[Ss](\d+)[Ee](\d+)', filename)
|
|
||||||
if match_s_e:
|
|
||||||
season = int(match_s_e.group(1))
|
|
||||||
episode = int(match_s_e.group(2))
|
|
||||||
return season * 1000 + episode
|
|
||||||
|
|
||||||
# 2.2 E01/EP01 格式,仅提取集数
|
|
||||||
match_e = re.search(r'[Ee][Pp]?(\d+)', filename)
|
|
||||||
if match_e:
|
|
||||||
return int(match_e.group(1))
|
|
||||||
|
|
||||||
# 2.3 1x01 格式,提取季数和集数
|
|
||||||
match_x = re.search(r'(\d+)[Xx](\d+)', filename)
|
|
||||||
if match_x:
|
|
||||||
season = int(match_x.group(1))
|
|
||||||
episode = int(match_x.group(2))
|
|
||||||
return season * 1000 + episode
|
|
||||||
|
|
||||||
# 2.4 数字后接4K格式
|
|
||||||
match_4k = re.search(r'(\d+)[-_\s]*4[Kk]', filename)
|
|
||||||
if match_4k:
|
|
||||||
return int(match_4k.group(1))
|
|
||||||
|
|
||||||
# 2.5 方括号包围的数字
|
|
||||||
match_bracket = re.search(r'\[(\d+)\]', filename)
|
|
||||||
if match_bracket:
|
|
||||||
return int(match_bracket.group(1))
|
|
||||||
|
|
||||||
# 2.6 中括号包围的数字
|
|
||||||
match_cn_bracket = re.search(r'【(\d+)】', filename)
|
|
||||||
if match_cn_bracket:
|
|
||||||
return int(match_cn_bracket.group(1))
|
|
||||||
|
|
||||||
# 2.7 下划线包围的数字
|
|
||||||
match_underscore = re.search(r'_?(\d+)_', filename)
|
|
||||||
if match_underscore:
|
|
||||||
return int(match_underscore.group(1))
|
|
||||||
|
|
||||||
# 3. 日期格式识别(支持多种格式)
|
|
||||||
|
|
||||||
# 3.1 完整的YYYYMMDD格式
|
|
||||||
match_date_compact = re.search(r'(20\d{2})(\d{2})(\d{2})', filename)
|
|
||||||
if match_date_compact:
|
|
||||||
year = int(match_date_compact.group(1))
|
|
||||||
month = int(match_date_compact.group(2))
|
|
||||||
day = int(match_date_compact.group(3))
|
|
||||||
return year * 10000 + month * 100 + day
|
|
||||||
|
|
||||||
# 3.2 YYYY-MM-DD 或 YYYY.MM.DD 或 YYYY/MM/DD 格式
|
|
||||||
match_date_full = re.search(r'(20\d{2})[-./](\d{1,2})[-./](\d{1,2})', filename)
|
|
||||||
if match_date_full:
|
|
||||||
year = int(match_date_full.group(1))
|
|
||||||
month = int(match_date_full.group(2))
|
|
||||||
day = int(match_date_full.group(3))
|
|
||||||
return year * 10000 + month * 100 + day
|
|
||||||
|
|
||||||
# 3.3 MM/DD/YYYY 或 DD/MM/YYYY 格式
|
|
||||||
match_date_alt = re.search(r'(\d{1,2})[-./](\d{1,2})[-./](20\d{2})', filename)
|
|
||||||
if match_date_alt:
|
|
||||||
# 假设第一个是月,第二个是日(美式日期)
|
|
||||||
month = int(match_date_alt.group(1))
|
|
||||||
day = int(match_date_alt.group(2))
|
|
||||||
year = int(match_date_alt.group(3))
|
|
||||||
# 检查月份值,如果大于12可能是欧式日期格式(DD/MM/YYYY)
|
|
||||||
if month > 12:
|
|
||||||
month, day = day, month
|
|
||||||
return year * 10000 + month * 100 + day
|
|
||||||
|
|
||||||
# 3.4 MM/DD 格式(无年份),假设为当前年
|
|
||||||
match_date_short = re.search(r'(\d{1,2})[-./](\d{1,2})', filename)
|
|
||||||
if match_date_short:
|
|
||||||
# 假设第一个是月,第二个是日
|
|
||||||
month = int(match_date_short.group(1))
|
|
||||||
day = int(match_date_short.group(2))
|
|
||||||
# 检查月份值,如果大于12可能是欧式日期格式(DD/MM)
|
|
||||||
if month > 12:
|
|
||||||
month, day = day, month
|
|
||||||
# 由于没有年份,使用一个较低的基数,确保任何有年份的日期都排在后面
|
|
||||||
return month * 100 + day
|
|
||||||
|
|
||||||
# 3.5 年期格式,如"2025年14期"
|
|
||||||
match_year_issue = re.search(r'(20\d{2})[年].*?(\d+)[期]', filename)
|
|
||||||
if match_year_issue:
|
|
||||||
year = int(match_year_issue.group(1))
|
|
||||||
issue = int(match_year_issue.group(2))
|
|
||||||
return year * 1000 + issue
|
|
||||||
|
|
||||||
# 3.6 日期+期数的复合格式,例如:2025-04-18 第5期上
|
|
||||||
match_date_episode = re.search(r'(20\d{2})[-./](\d{1,2})[-./](\d{1,2}).*?第(\d+)[期集话]', filename)
|
|
||||||
if match_date_episode:
|
|
||||||
year = int(match_date_episode.group(1))
|
|
||||||
month = int(match_date_episode.group(2))
|
|
||||||
day = int(match_date_episode.group(3))
|
|
||||||
episode = int(match_date_episode.group(4))
|
|
||||||
date_val = year * 10000 + month * 100 + day
|
|
||||||
# 将日期值作为主排序,期数为次要排序
|
|
||||||
if '上' in filename:
|
|
||||||
return date_val * 100 + episode * 10 + 1
|
|
||||||
elif '中' in filename:
|
|
||||||
return date_val * 100 + episode * 10 + 2
|
|
||||||
elif '下' in filename:
|
|
||||||
return date_val * 100 + episode * 10 + 3
|
|
||||||
return date_val * 100 + episode * 10
|
|
||||||
|
|
||||||
# 4. 纯数字格式(文件名开头是纯数字)
|
|
||||||
match_num = re.match(r'^(\d+)', file_name_without_ext)
|
|
||||||
if match_num:
|
|
||||||
return int(match_num.group(1))
|
|
||||||
|
|
||||||
# 5. 尝试匹配文件名中的任何数字
|
|
||||||
any_num_match = re.search(r'(\d+)', filename)
|
|
||||||
if any_num_match:
|
|
||||||
return int(any_num_match.group(1))
|
|
||||||
|
|
||||||
# 6. 默认使用更新时间
|
|
||||||
return file.get("created_at", file.get("updated_at", file.get("last_update_at", 0)))
|
|
||||||
|
|
||||||
# 过滤出非目录文件,并且排除已经符合命名规则的文件
|
# 过滤出非目录文件,并且排除已经符合命名规则的文件
|
||||||
files_to_process = []
|
files_to_process = []
|
||||||
@ -570,11 +420,8 @@ def get_share_detail():
|
|||||||
if episode_num is not None:
|
if episode_num is not None:
|
||||||
return episode_num
|
return episode_num
|
||||||
|
|
||||||
# 如果无法提取序号,则使用更新时间
|
# 如果无法提取剧集号,则使用通用的排序函数
|
||||||
try:
|
return sort_file_by_name(file)
|
||||||
return file.get("last_update_at", 0)
|
|
||||||
except:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
# 过滤出非目录文件,并且排除已经符合命名规则的文件
|
# 过滤出非目录文件,并且排除已经符合命名规则的文件
|
||||||
files_to_process = []
|
files_to_process = []
|
||||||
|
|||||||
@ -18,7 +18,213 @@ import importlib
|
|||||||
import urllib.parse
|
import urllib.parse
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
# 统一的剧集编号提取函数
|
# 全局的文件排序函数
|
||||||
|
def sort_file_by_name(file):
|
||||||
|
"""
|
||||||
|
通用的文件排序函数,用于根据文件名智能排序
|
||||||
|
支持多种格式的日期、期数、集数等提取和排序
|
||||||
|
"""
|
||||||
|
if isinstance(file, dict) and file.get("dir", False): # 跳过文件夹
|
||||||
|
return float('inf')
|
||||||
|
|
||||||
|
# 获取文件名,支持字符串或文件对象
|
||||||
|
if isinstance(file, dict):
|
||||||
|
filename = file.get("file_name", "")
|
||||||
|
else:
|
||||||
|
filename = file
|
||||||
|
|
||||||
|
# 提取文件名,不含扩展名
|
||||||
|
file_name_without_ext = os.path.splitext(filename)[0]
|
||||||
|
|
||||||
|
# 1. 日期格式识别(支持多种格式)- 最高优先级
|
||||||
|
|
||||||
|
# 1.1 日期+期数的复合格式,例如:2025-04-18 第5期上
|
||||||
|
match_date_episode = re.search(r'(20\d{2})[-./\s](\d{1,2})[-./\s](\d{1,2}).*?第(\d+)[期集话]', filename)
|
||||||
|
if match_date_episode:
|
||||||
|
year = int(match_date_episode.group(1))
|
||||||
|
month = int(match_date_episode.group(2))
|
||||||
|
day = int(match_date_episode.group(3))
|
||||||
|
episode = int(match_date_episode.group(4))
|
||||||
|
date_val = year * 10000 + month * 100 + day
|
||||||
|
# 将日期值作为主排序,期数为次要排序
|
||||||
|
if '上' in filename:
|
||||||
|
return date_val * 100 + episode * 10 + 1
|
||||||
|
elif '中' in filename:
|
||||||
|
return date_val * 100 + episode * 10 + 2
|
||||||
|
elif '下' in filename:
|
||||||
|
return date_val * 100 + episode * 10 + 3
|
||||||
|
return date_val * 100 + episode * 10
|
||||||
|
|
||||||
|
# 1.2 使用两位年份的日期+期数格式,如:23-04-18 第5期
|
||||||
|
match_yy_date_episode = re.search(r'((?:19|20)?\d{2})[-./\s](\d{1,2})[-./\s](\d{1,2}).*?第(\d+)[期集话]', filename)
|
||||||
|
if match_yy_date_episode and len(match_yy_date_episode.group(1)) == 2:
|
||||||
|
year_str = match_yy_date_episode.group(1)
|
||||||
|
# 如果是两位年份,假设20xx年
|
||||||
|
year = int("20" + year_str)
|
||||||
|
month = int(match_yy_date_episode.group(2))
|
||||||
|
day = int(match_yy_date_episode.group(3))
|
||||||
|
episode = int(match_yy_date_episode.group(4))
|
||||||
|
date_val = year * 10000 + month * 100 + day
|
||||||
|
if '上' in filename:
|
||||||
|
return date_val * 100 + episode * 10 + 1
|
||||||
|
elif '中' in filename:
|
||||||
|
return date_val * 100 + episode * 10 + 2
|
||||||
|
elif '下' in filename:
|
||||||
|
return date_val * 100 + episode * 10 + 3
|
||||||
|
return date_val * 100 + episode * 10
|
||||||
|
|
||||||
|
# 1.3 完整的YYYYMMDD格式(无分隔符)
|
||||||
|
match_date_compact = re.search(r'((?:19|20)\d{2})(\d{2})(\d{2})', filename)
|
||||||
|
if match_date_compact:
|
||||||
|
year = int(match_date_compact.group(1))
|
||||||
|
month = int(match_date_compact.group(2))
|
||||||
|
day = int(match_date_compact.group(3))
|
||||||
|
return year * 10000 + month * 100 + day
|
||||||
|
|
||||||
|
# 1.4 YYYY-MM-DD 或 YYYY.MM.DD 或 YYYY/MM/DD 或 YYYY MM DD格式
|
||||||
|
match_date_full = re.search(r'((?:19|20)\d{2})[-./\s](\d{1,2})[-./\s](\d{1,2})', filename)
|
||||||
|
if match_date_full:
|
||||||
|
year = int(match_date_full.group(1))
|
||||||
|
month = int(match_date_full.group(2))
|
||||||
|
day = int(match_date_full.group(3))
|
||||||
|
return year * 10000 + month * 100 + day
|
||||||
|
|
||||||
|
# 1.5 YY-MM-DD 或 YY.MM.DD 或 YY/MM/DD 或 YY MM DD格式(两位年份)
|
||||||
|
match_yy_date = re.search(r'((?:19|20)?\d{2})[-./\s](\d{1,2})[-./\s](\d{1,2})', filename)
|
||||||
|
if match_yy_date and len(match_yy_date.group(1)) == 2:
|
||||||
|
year_str = match_yy_date.group(1)
|
||||||
|
# 如果是两位年份,假设20xx年
|
||||||
|
year = int("20" + year_str)
|
||||||
|
month = int(match_yy_date.group(2))
|
||||||
|
day = int(match_yy_date.group(3))
|
||||||
|
return year * 10000 + month * 100 + day
|
||||||
|
|
||||||
|
# 1.6 YYMMDD格式(两位年份,无分隔符)
|
||||||
|
match_yy_compact = re.search(r'(?<!\d)(\d{2})(\d{2})(\d{2})(?!\d)', filename)
|
||||||
|
if match_yy_compact:
|
||||||
|
year_str = match_yy_compact.group(1)
|
||||||
|
# 检查月份和日期的有效性
|
||||||
|
month = int(match_yy_compact.group(2))
|
||||||
|
day = int(match_yy_compact.group(3))
|
||||||
|
if 1 <= month <= 12 and 1 <= day <= 31:
|
||||||
|
# 合理的月份和日期,假设为YY-MM-DD
|
||||||
|
year = int("20" + year_str)
|
||||||
|
return year * 10000 + month * 100 + day
|
||||||
|
|
||||||
|
# 1.7 MM/DD/YYYY 或 DD/MM/YYYY 格式
|
||||||
|
match_date_alt = re.search(r'(\d{1,2})[-./\s](\d{1,2})[-./\s]((?:19|20)\d{2})', filename)
|
||||||
|
if match_date_alt:
|
||||||
|
# 假设第一个是月,第二个是日(美式日期)
|
||||||
|
month = int(match_date_alt.group(1))
|
||||||
|
day = int(match_date_alt.group(2))
|
||||||
|
year = int(match_date_alt.group(3))
|
||||||
|
# 检查月份值,如果大于12可能是欧式日期格式(DD/MM/YYYY)
|
||||||
|
if month > 12:
|
||||||
|
month, day = day, month
|
||||||
|
return year * 10000 + month * 100 + day
|
||||||
|
|
||||||
|
# 1.8 年期格式,如"2025年14期"
|
||||||
|
match_year_issue = re.search(r'((?:19|20)\d{2})[年].*?(\d+)[期]', filename)
|
||||||
|
if match_year_issue:
|
||||||
|
year = int(match_year_issue.group(1))
|
||||||
|
issue = int(match_year_issue.group(2))
|
||||||
|
return year * 1000 + issue
|
||||||
|
|
||||||
|
# 1.9 MM-DD 或 MM.DD 或 MM/DD 或 MM DD格式(无年份),假设为当前年
|
||||||
|
match_date_short = re.search(r'(?<!\d)(\d{1,2})[-./\s](\d{1,2})(?!\d)', filename)
|
||||||
|
if match_date_short:
|
||||||
|
# 假设第一个是月,第二个是日
|
||||||
|
month = int(match_date_short.group(1))
|
||||||
|
day = int(match_date_short.group(2))
|
||||||
|
# 检查月份值,如果大于12可能是欧式日期格式(DD/MM)
|
||||||
|
if month > 12:
|
||||||
|
month, day = day, month
|
||||||
|
# 由于没有年份,使用一个较低的基数,确保任何有年份的日期都排在后面
|
||||||
|
return month * 100 + day
|
||||||
|
|
||||||
|
# 2. "第X期/集/话" 格式
|
||||||
|
match_chinese = re.search(r'第(\d+)[期集话]', filename)
|
||||||
|
episode_num = int(match_chinese.group(1)) if match_chinese else 0
|
||||||
|
|
||||||
|
# 文件名含"上中下"(优先处理,因为可能与其他格式同时存在)
|
||||||
|
if match_chinese:
|
||||||
|
# 如果同时存在集数和上中下,则按照集数*10+位置排序
|
||||||
|
if '上' in filename:
|
||||||
|
return episode_num * 10 + 1
|
||||||
|
elif '中' in filename:
|
||||||
|
return episode_num * 10 + 2
|
||||||
|
elif '下' in filename:
|
||||||
|
return episode_num * 10 + 3
|
||||||
|
return episode_num * 10
|
||||||
|
elif '上' in filename:
|
||||||
|
return 1
|
||||||
|
elif '中' in filename:
|
||||||
|
return 2
|
||||||
|
elif '下' in filename:
|
||||||
|
return 3
|
||||||
|
|
||||||
|
# 2.1 "X集/期/话" 格式
|
||||||
|
match_chinese_simple = re.search(r'(\d+)[期集话]', filename)
|
||||||
|
if match_chinese_simple:
|
||||||
|
return int(match_chinese_simple.group(1))
|
||||||
|
|
||||||
|
# 3.1 S01E01 格式,提取季数和集数
|
||||||
|
match_s_e = re.search(r'[Ss](\d+)[Ee](\d+)', filename)
|
||||||
|
if match_s_e:
|
||||||
|
season = int(match_s_e.group(1))
|
||||||
|
episode = int(match_s_e.group(2))
|
||||||
|
return season * 1000 + episode
|
||||||
|
|
||||||
|
# 3.2 E01/EP01 格式,仅提取集数
|
||||||
|
match_e = re.search(r'[Ee][Pp]?(\d+)', filename)
|
||||||
|
if match_e:
|
||||||
|
return int(match_e.group(1))
|
||||||
|
|
||||||
|
# 3.3 1x01 格式,提取季数和集数
|
||||||
|
match_x = re.search(r'(\d+)[Xx](\d+)', filename)
|
||||||
|
if match_x:
|
||||||
|
season = int(match_x.group(1))
|
||||||
|
episode = int(match_x.group(2))
|
||||||
|
return season * 1000 + episode
|
||||||
|
|
||||||
|
# 3.4 数字后接4K格式
|
||||||
|
match_4k = re.search(r'(\d+)[-_\s]*4[Kk]', filename)
|
||||||
|
if match_4k:
|
||||||
|
return int(match_4k.group(1))
|
||||||
|
|
||||||
|
# 3.5 方括号包围的数字
|
||||||
|
match_bracket = re.search(r'\[(\d+)\]', filename)
|
||||||
|
if match_bracket:
|
||||||
|
return int(match_bracket.group(1))
|
||||||
|
|
||||||
|
# 3.6 中括号包围的数字
|
||||||
|
match_cn_bracket = re.search(r'【(\d+)】', filename)
|
||||||
|
if match_cn_bracket:
|
||||||
|
return int(match_cn_bracket.group(1))
|
||||||
|
|
||||||
|
# 3.7 下划线包围的数字
|
||||||
|
match_underscore = re.search(r'_?(\d+)_', filename)
|
||||||
|
if match_underscore:
|
||||||
|
return int(match_underscore.group(1))
|
||||||
|
|
||||||
|
# 4. 纯数字格式(文件名开头是纯数字)
|
||||||
|
match_num = re.match(r'^(\d+)', file_name_without_ext)
|
||||||
|
if match_num:
|
||||||
|
return int(match_num.group(1))
|
||||||
|
|
||||||
|
# 5. 尝试匹配文件名中的任何数字
|
||||||
|
any_num_match = re.search(r'(\d+)', filename)
|
||||||
|
if any_num_match:
|
||||||
|
return int(any_num_match.group(1))
|
||||||
|
|
||||||
|
# 6. 默认使用更新时间
|
||||||
|
if isinstance(file, dict):
|
||||||
|
return file.get("created_at", file.get("updated_at", file.get("last_update_at", 0)))
|
||||||
|
|
||||||
|
return float('inf')
|
||||||
|
|
||||||
|
|
||||||
|
# 全局的剧集编号提取函数
|
||||||
def extract_episode_number(filename, episode_patterns=None, config_data=None):
|
def extract_episode_number(filename, episode_patterns=None, config_data=None):
|
||||||
"""
|
"""
|
||||||
从文件名中提取剧集编号
|
从文件名中提取剧集编号
|
||||||
@ -1099,186 +1305,16 @@ class Quark:
|
|||||||
|
|
||||||
# 实现高级排序算法
|
# 实现高级排序算法
|
||||||
def extract_sorting_value(file):
|
def extract_sorting_value(file):
|
||||||
if file.get("dir", False): # 跳过文件夹
|
# 使用全局排序函数
|
||||||
return float('inf')
|
return sort_file_by_name(file)
|
||||||
|
|
||||||
filename = file["file_name"]
|
# 判断是否使用单独的{}模式
|
||||||
|
|
||||||
# 提取文件名,不含扩展名
|
|
||||||
file_name_without_ext = os.path.splitext(filename)[0]
|
|
||||||
|
|
||||||
# 1. "第X期/集/话" 格式 - 保持最高优先级
|
|
||||||
match_chinese = re.search(r'第(\d+)[期集话]', filename)
|
|
||||||
episode_num = int(match_chinese.group(1)) if match_chinese else 0
|
|
||||||
|
|
||||||
# 5. 文件名含"上中下"(优先处理,因为可能与其他格式同时存在)
|
|
||||||
if match_chinese:
|
|
||||||
# 如果同时存在集数和上中下,则按照集数*10+位置排序
|
|
||||||
if '上' in filename:
|
|
||||||
return episode_num * 10 + 1
|
|
||||||
elif '中' in filename:
|
|
||||||
return episode_num * 10 + 2
|
|
||||||
elif '下' in filename:
|
|
||||||
return episode_num * 10 + 3
|
|
||||||
return episode_num * 10
|
|
||||||
elif '上' in filename:
|
|
||||||
return 1
|
|
||||||
elif '中' in filename:
|
|
||||||
return 2
|
|
||||||
elif '下' in filename:
|
|
||||||
return 3
|
|
||||||
|
|
||||||
# 1.2 "X集/期/话" 格式 - 与我们修改后的优先级一致
|
|
||||||
match_chinese_simple = re.search(r'(\d+)[期集话]', filename)
|
|
||||||
if match_chinese_simple:
|
|
||||||
return int(match_chinese_simple.group(1))
|
|
||||||
|
|
||||||
# 2.1 S01E01 格式,提取季数和集数
|
|
||||||
match_s_e = re.search(r'[Ss](\d+)[Ee](\d+)', filename)
|
|
||||||
if match_s_e:
|
|
||||||
season = int(match_s_e.group(1))
|
|
||||||
episode = int(match_s_e.group(2))
|
|
||||||
return season * 1000 + episode
|
|
||||||
|
|
||||||
# 2.2 E01/EP01 格式,仅提取集数
|
|
||||||
match_e = re.search(r'[Ee][Pp]?(\d+)', filename)
|
|
||||||
if match_e:
|
|
||||||
return int(match_e.group(1))
|
|
||||||
|
|
||||||
# 2.3 1x01 格式,提取季数和集数
|
|
||||||
match_x = re.search(r'(\d+)[Xx](\d+)', filename)
|
|
||||||
if match_x:
|
|
||||||
season = int(match_x.group(1))
|
|
||||||
episode = int(match_x.group(2))
|
|
||||||
return season * 1000 + episode
|
|
||||||
|
|
||||||
# 2.4 数字后接4K格式
|
|
||||||
match_4k = re.search(r'(\d+)[-_\s]*4[Kk]', filename)
|
|
||||||
if match_4k:
|
|
||||||
return int(match_4k.group(1))
|
|
||||||
|
|
||||||
# 2.5 方括号包围的数字
|
|
||||||
match_bracket = re.search(r'\[(\d+)\]', filename)
|
|
||||||
if match_bracket:
|
|
||||||
return int(match_bracket.group(1))
|
|
||||||
|
|
||||||
# 2.6 中括号包围的数字
|
|
||||||
match_cn_bracket = re.search(r'【(\d+)】', filename)
|
|
||||||
if match_cn_bracket:
|
|
||||||
return int(match_cn_bracket.group(1))
|
|
||||||
|
|
||||||
# 2.7 下划线包围的数字
|
|
||||||
match_underscore = re.search(r'_?(\d+)_', filename)
|
|
||||||
if match_underscore:
|
|
||||||
return int(match_underscore.group(1))
|
|
||||||
|
|
||||||
# 3. 日期格式识别(支持多种格式)
|
|
||||||
|
|
||||||
# 3.1 完整的YYYYMMDD格式
|
|
||||||
match_date_compact = re.search(r'(20\d{2})(\d{2})(\d{2})', filename)
|
|
||||||
if match_date_compact:
|
|
||||||
year = int(match_date_compact.group(1))
|
|
||||||
month = int(match_date_compact.group(2))
|
|
||||||
day = int(match_date_compact.group(3))
|
|
||||||
return year * 10000 + month * 100 + day
|
|
||||||
|
|
||||||
# 3.2 YYYY-MM-DD 或 YYYY.MM.DD 或 YYYY/MM/DD 格式
|
|
||||||
match_date_full = re.search(r'(20\d{2})[-./](\d{1,2})[-./](\d{1,2})', filename)
|
|
||||||
if match_date_full:
|
|
||||||
year = int(match_date_full.group(1))
|
|
||||||
month = int(match_date_full.group(2))
|
|
||||||
day = int(match_date_full.group(3))
|
|
||||||
return year * 10000 + month * 100 + day
|
|
||||||
|
|
||||||
# 3.3 MM/DD/YYYY 或 DD/MM/YYYY 格式
|
|
||||||
match_date_alt = re.search(r'(\d{1,2})[-./](\d{1,2})[-./](20\d{2})', filename)
|
|
||||||
if match_date_alt:
|
|
||||||
# 假设第一个是月,第二个是日(美式日期)
|
|
||||||
month = int(match_date_alt.group(1))
|
|
||||||
day = int(match_date_alt.group(2))
|
|
||||||
year = int(match_date_alt.group(3))
|
|
||||||
# 检查月份值,如果大于12可能是欧式日期格式(DD/MM/YYYY)
|
|
||||||
if month > 12:
|
|
||||||
month, day = day, month
|
|
||||||
return year * 10000 + month * 100 + day
|
|
||||||
|
|
||||||
# 3.4 MM/DD 格式(无年份),假设为当前年
|
|
||||||
match_date_short = re.search(r'(\d{1,2})[-./](\d{1,2})', filename)
|
|
||||||
if match_date_short:
|
|
||||||
# 假设第一个是月,第二个是日
|
|
||||||
month = int(match_date_short.group(1))
|
|
||||||
day = int(match_date_short.group(2))
|
|
||||||
# 检查月份值,如果大于12可能是欧式日期格式(DD/MM)
|
|
||||||
if month > 12:
|
|
||||||
month, day = day, month
|
|
||||||
# 由于没有年份,使用一个较低的基数,确保任何有年份的日期都排在后面
|
|
||||||
return month * 100 + day
|
|
||||||
|
|
||||||
# 3.5 年期格式,如"2025年14期"
|
|
||||||
match_year_issue = re.search(r'(20\d{2})[年].*?(\d+)[期]', filename)
|
|
||||||
if match_year_issue:
|
|
||||||
year = int(match_year_issue.group(1))
|
|
||||||
issue = int(match_year_issue.group(2))
|
|
||||||
return year * 1000 + issue
|
|
||||||
|
|
||||||
# 3.6 日期+期数的复合格式,例如:2025-04-18 第5期上
|
|
||||||
match_date_episode = re.search(r'(20\d{2})[-./](\d{1,2})[-./](\d{1,2}).*?第(\d+)[期集话]', filename)
|
|
||||||
if match_date_episode:
|
|
||||||
year = int(match_date_episode.group(1))
|
|
||||||
month = int(match_date_episode.group(2))
|
|
||||||
day = int(match_date_episode.group(3))
|
|
||||||
episode = int(match_date_episode.group(4))
|
|
||||||
date_val = year * 10000 + month * 100 + day
|
|
||||||
# 将日期值作为主排序,期数为次要排序
|
|
||||||
if '上' in filename:
|
|
||||||
return date_val * 100 + episode * 10 + 1
|
|
||||||
elif '中' in filename:
|
|
||||||
return date_val * 100 + episode * 10 + 2
|
|
||||||
elif '下' in filename:
|
|
||||||
return date_val * 100 + episode * 10 + 3
|
|
||||||
return date_val * 100 + episode * 10
|
|
||||||
|
|
||||||
# 4. 纯数字格式(文件名开头是纯数字)
|
|
||||||
match_num = re.match(r'^(\d+)', file_name_without_ext)
|
|
||||||
if match_num:
|
|
||||||
return int(match_num.group(1))
|
|
||||||
|
|
||||||
# 5. 尝试匹配文件名中的任何数字
|
|
||||||
any_num_match = re.search(r'(\d+)', filename)
|
|
||||||
if any_num_match:
|
|
||||||
return int(any_num_match.group(1))
|
|
||||||
|
|
||||||
# 6. 默认使用更新时间
|
|
||||||
return file.get("created_at", file.get("updated_at", file.get("last_update_at", 0)))
|
|
||||||
|
|
||||||
# 过滤出非目录文件,排除已经排除掉的重复文件,然后排序
|
|
||||||
files_to_process = []
|
|
||||||
for f in filtered_share_files:
|
|
||||||
if f["dir"]:
|
|
||||||
continue # 跳过文件夹
|
|
||||||
|
|
||||||
# 检查文件是否已符合命名规则
|
|
||||||
if sequence_pattern == "{}":
|
|
||||||
# 对于单独的{},检查文件名是否为纯数字
|
|
||||||
file_name_without_ext = os.path.splitext(f["file_name"])[0]
|
|
||||||
if file_name_without_ext.isdigit():
|
|
||||||
# 增加判断:如果是日期格式的纯数字,不视为已命名
|
|
||||||
if not is_date_format(file_name_without_ext):
|
|
||||||
continue # 跳过已符合命名规则的文件
|
|
||||||
elif re.match(regex_pattern, f["file_name"]):
|
|
||||||
continue # 跳过已符合命名规则的文件
|
|
||||||
|
|
||||||
# 添加到待处理文件列表
|
|
||||||
files_to_process.append(f)
|
|
||||||
|
|
||||||
# 根据提取的排序值进行排序
|
|
||||||
sorted_files = sorted(files_to_process, key=extract_sorting_value)
|
|
||||||
|
|
||||||
# 需保存的文件清单
|
# 需保存的文件清单
|
||||||
need_save_list = []
|
need_save_list = []
|
||||||
|
|
||||||
# 为每个文件分配序号
|
# 为每个文件分配序号
|
||||||
for share_file in sorted_files:
|
for share_file in filtered_share_files:
|
||||||
# 获取文件扩展名
|
# 获取文件扩展名
|
||||||
file_ext = os.path.splitext(share_file["file_name"])[1]
|
file_ext = os.path.splitext(share_file["file_name"])[1]
|
||||||
# 生成新文件名
|
# 生成新文件名
|
||||||
@ -1691,157 +1727,10 @@ class Quark:
|
|||||||
|
|
||||||
# 实现高级排序算法
|
# 实现高级排序算法
|
||||||
def extract_sorting_value(file):
|
def extract_sorting_value(file):
|
||||||
if file.get("dir", False): # 跳过文件夹
|
# 使用全局排序函数
|
||||||
return float('inf')
|
return sort_file_by_name(file)
|
||||||
|
|
||||||
filename = file["file_name"]
|
# 判断是否使用单独的{}模式
|
||||||
|
|
||||||
# 提取文件名,不含扩展名
|
|
||||||
file_name_without_ext = os.path.splitext(filename)[0]
|
|
||||||
|
|
||||||
# 1. "第X期/集/话" 格式 - 保持最高优先级
|
|
||||||
match_chinese = re.search(r'第(\d+)[期集话]', filename)
|
|
||||||
episode_num = int(match_chinese.group(1)) if match_chinese else 0
|
|
||||||
|
|
||||||
# 5. 文件名含"上中下"(优先处理,因为可能与其他格式同时存在)
|
|
||||||
if match_chinese:
|
|
||||||
# 如果同时存在集数和上中下,则按照集数*10+位置排序
|
|
||||||
if '上' in filename:
|
|
||||||
return episode_num * 10 + 1
|
|
||||||
elif '中' in filename:
|
|
||||||
return episode_num * 10 + 2
|
|
||||||
elif '下' in filename:
|
|
||||||
return episode_num * 10 + 3
|
|
||||||
return episode_num * 10
|
|
||||||
elif '上' in filename:
|
|
||||||
return 1
|
|
||||||
elif '中' in filename:
|
|
||||||
return 2
|
|
||||||
elif '下' in filename:
|
|
||||||
return 3
|
|
||||||
|
|
||||||
# 1.2 "X集/期/话" 格式 - 与我们修改后的优先级一致
|
|
||||||
match_chinese_simple = re.search(r'(\d+)[期集话]', filename)
|
|
||||||
if match_chinese_simple:
|
|
||||||
return int(match_chinese_simple.group(1))
|
|
||||||
|
|
||||||
# 2.1 S01E01 格式,提取季数和集数
|
|
||||||
match_s_e = re.search(r'[Ss](\d+)[Ee](\d+)', filename)
|
|
||||||
if match_s_e:
|
|
||||||
season = int(match_s_e.group(1))
|
|
||||||
episode = int(match_s_e.group(2))
|
|
||||||
return season * 1000 + episode
|
|
||||||
|
|
||||||
# 2.2 E01/EP01 格式,仅提取集数
|
|
||||||
match_e = re.search(r'[Ee][Pp]?(\d+)', filename)
|
|
||||||
if match_e:
|
|
||||||
return int(match_e.group(1))
|
|
||||||
|
|
||||||
# 2.3 1x01 格式,提取季数和集数
|
|
||||||
match_x = re.search(r'(\d+)[Xx](\d+)', filename)
|
|
||||||
if match_x:
|
|
||||||
season = int(match_x.group(1))
|
|
||||||
episode = int(match_x.group(2))
|
|
||||||
return season * 1000 + episode
|
|
||||||
|
|
||||||
# 2.4 数字后接4K格式
|
|
||||||
match_4k = re.search(r'(\d+)[-_\s]*4[Kk]', filename)
|
|
||||||
if match_4k:
|
|
||||||
return int(match_4k.group(1))
|
|
||||||
|
|
||||||
# 2.5 方括号包围的数字
|
|
||||||
match_bracket = re.search(r'\[(\d+)\]', filename)
|
|
||||||
if match_bracket:
|
|
||||||
return int(match_bracket.group(1))
|
|
||||||
|
|
||||||
# 2.6 中括号包围的数字
|
|
||||||
match_cn_bracket = re.search(r'【(\d+)】', filename)
|
|
||||||
if match_cn_bracket:
|
|
||||||
return int(match_cn_bracket.group(1))
|
|
||||||
|
|
||||||
# 2.7 下划线包围的数字
|
|
||||||
match_underscore = re.search(r'_?(\d+)_', filename)
|
|
||||||
if match_underscore:
|
|
||||||
return int(match_underscore.group(1))
|
|
||||||
|
|
||||||
# 3. 日期格式识别(支持多种格式)
|
|
||||||
|
|
||||||
# 3.1 完整的YYYYMMDD格式
|
|
||||||
match_date_compact = re.search(r'(20\d{2})(\d{2})(\d{2})', filename)
|
|
||||||
if match_date_compact:
|
|
||||||
year = int(match_date_compact.group(1))
|
|
||||||
month = int(match_date_compact.group(2))
|
|
||||||
day = int(match_date_compact.group(3))
|
|
||||||
return year * 10000 + month * 100 + day
|
|
||||||
|
|
||||||
# 3.2 YYYY-MM-DD 或 YYYY.MM.DD 或 YYYY/MM/DD 格式
|
|
||||||
match_date_full = re.search(r'(20\d{2})[-./](\d{1,2})[-./](\d{1,2})', filename)
|
|
||||||
if match_date_full:
|
|
||||||
year = int(match_date_full.group(1))
|
|
||||||
month = int(match_date_full.group(2))
|
|
||||||
day = int(match_date_full.group(3))
|
|
||||||
return year * 10000 + month * 100 + day
|
|
||||||
|
|
||||||
# 3.3 MM/DD/YYYY 或 DD/MM/YYYY 格式
|
|
||||||
match_date_alt = re.search(r'(\d{1,2})[-./](\d{1,2})[-./](20\d{2})', filename)
|
|
||||||
if match_date_alt:
|
|
||||||
# 假设第一个是月,第二个是日(美式日期)
|
|
||||||
month = int(match_date_alt.group(1))
|
|
||||||
day = int(match_date_alt.group(2))
|
|
||||||
year = int(match_date_alt.group(3))
|
|
||||||
# 检查月份值,如果大于12可能是欧式日期格式(DD/MM/YYYY)
|
|
||||||
if month > 12:
|
|
||||||
month, day = day, month
|
|
||||||
return year * 10000 + month * 100 + day
|
|
||||||
|
|
||||||
# 3.4 MM/DD 格式(无年份),假设为当前年
|
|
||||||
match_date_short = re.search(r'(\d{1,2})[-./](\d{1,2})', filename)
|
|
||||||
if match_date_short:
|
|
||||||
# 假设第一个是月,第二个是日
|
|
||||||
month = int(match_date_short.group(1))
|
|
||||||
day = int(match_date_short.group(2))
|
|
||||||
# 检查月份值,如果大于12可能是欧式日期格式(DD/MM)
|
|
||||||
if month > 12:
|
|
||||||
month, day = day, month
|
|
||||||
# 由于没有年份,使用一个较低的基数,确保任何有年份的日期都排在后面
|
|
||||||
return month * 100 + day
|
|
||||||
|
|
||||||
# 3.5 年期格式,如"2025年14期"
|
|
||||||
match_year_issue = re.search(r'(20\d{2})[年].*?(\d+)[期]', filename)
|
|
||||||
if match_year_issue:
|
|
||||||
year = int(match_year_issue.group(1))
|
|
||||||
issue = int(match_year_issue.group(2))
|
|
||||||
return year * 1000 + issue
|
|
||||||
|
|
||||||
# 3.6 日期+期数的复合格式,例如:2025-04-18 第5期上
|
|
||||||
match_date_episode = re.search(r'(20\d{2})[-./](\d{1,2})[-./](\d{1,2}).*?第(\d+)[期集话]', filename)
|
|
||||||
if match_date_episode:
|
|
||||||
year = int(match_date_episode.group(1))
|
|
||||||
month = int(match_date_episode.group(2))
|
|
||||||
day = int(match_date_episode.group(3))
|
|
||||||
episode = int(match_date_episode.group(4))
|
|
||||||
date_val = year * 10000 + month * 100 + day
|
|
||||||
# 将日期值作为主排序,期数为次要排序
|
|
||||||
if '上' in filename:
|
|
||||||
return date_val * 100 + episode * 10 + 1
|
|
||||||
elif '中' in filename:
|
|
||||||
return date_val * 100 + episode * 10 + 2
|
|
||||||
elif '下' in filename:
|
|
||||||
return date_val * 100 + episode * 10 + 3
|
|
||||||
return date_val * 100 + episode * 10
|
|
||||||
|
|
||||||
# 4. 纯数字格式(文件名开头是纯数字)
|
|
||||||
match_num = re.match(r'^(\d+)', file_name_without_ext)
|
|
||||||
if match_num:
|
|
||||||
return int(match_num.group(1))
|
|
||||||
|
|
||||||
# 5. 尝试匹配文件名中的任何数字
|
|
||||||
any_num_match = re.search(r'(\d+)', filename)
|
|
||||||
if any_num_match:
|
|
||||||
return int(any_num_match.group(1))
|
|
||||||
|
|
||||||
# 6. 默认使用更新时间
|
|
||||||
return file.get("created_at", file.get("updated_at", file.get("last_update_at", 0)))
|
|
||||||
|
|
||||||
# 初始化sorted_files列表,用于收集需要重命名的文件
|
# 初始化sorted_files列表,用于收集需要重命名的文件
|
||||||
sorted_files = []
|
sorted_files = []
|
||||||
@ -2492,29 +2381,8 @@ class Quark:
|
|||||||
|
|
||||||
# 修改为按日期或数字排序(复用与文件树相同的排序逻辑)
|
# 修改为按日期或数字排序(复用与文件树相同的排序逻辑)
|
||||||
def extract_sort_value(file_name):
|
def extract_sort_value(file_name):
|
||||||
# 尝试提取日期格式(优先YYYY-MM-DD格式)
|
# 使用全局排序函数
|
||||||
date_match = re.search(r'(\d{4})[-./](\d{1,2})[-./](\d{1,2})', file_name)
|
return sort_file_by_name(file_name)
|
||||||
if date_match:
|
|
||||||
year = int(date_match.group(1))
|
|
||||||
month = int(date_match.group(2))
|
|
||||||
day = int(date_match.group(3))
|
|
||||||
return year * 10000 + month * 100 + day
|
|
||||||
|
|
||||||
# 尝试提取紧凑日期格式(YYYYMMDD)
|
|
||||||
compact_date_match = re.search(r'(\d{4})(\d{2})(\d{2})', file_name)
|
|
||||||
if compact_date_match:
|
|
||||||
year = int(compact_date_match.group(1))
|
|
||||||
month = int(compact_date_match.group(2))
|
|
||||||
day = int(compact_date_match.group(3))
|
|
||||||
return year * 10000 + month * 100 + day
|
|
||||||
|
|
||||||
# 尝试提取任何数字
|
|
||||||
number_match = re.search(r'(\d+)', file_name)
|
|
||||||
if number_match:
|
|
||||||
return int(number_match.group(1))
|
|
||||||
|
|
||||||
# 默认使用原文件名
|
|
||||||
return float('inf')
|
|
||||||
|
|
||||||
# 按目标文件名中的日期或数字进行排序,与顺序命名和剧集命名模式保持一致
|
# 按目标文件名中的日期或数字进行排序,与顺序命名和剧集命名模式保持一致
|
||||||
rename_operations.sort(key=lambda x: extract_sort_value(x[1]))
|
rename_operations.sort(key=lambda x: extract_sort_value(x[1]))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user