mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 23:47:41 +08:00
perf: optimize torrent filtering
This commit is contained in:
+47
-15
@@ -1,5 +1,6 @@
|
||||
import datetime
|
||||
import re
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
from typing import Tuple, Optional, List, Union, Dict, Any
|
||||
from urllib.parse import unquote
|
||||
@@ -19,6 +20,40 @@ from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
_SIZE_UNIT = 1024 * 1024
|
||||
|
||||
|
||||
@lru_cache(maxsize=512)
|
||||
def _compile_filter_pattern(pattern: str) -> re.Pattern:
|
||||
"""
|
||||
编译订阅/工作流附加过滤正则。
|
||||
用户输入沿用原本的正则语义,缓存只减少同一规则反复匹配大量种子时的编译成本。
|
||||
"""
|
||||
return re.compile(r"%s" % pattern, re.I)
|
||||
|
||||
|
||||
def _filter_pattern_search(pattern: Union[str, int, float], content: str) -> bool:
|
||||
"""
|
||||
按原有字符串插值语义执行过滤正则匹配。
|
||||
"""
|
||||
return bool(_compile_filter_pattern(str(pattern)).search(content))
|
||||
|
||||
|
||||
@lru_cache(maxsize=256)
|
||||
def _parse_filter_size_range(size_range: str) -> Tuple[str, float, Optional[float]]:
|
||||
"""
|
||||
解析附加过滤的大小范围,单位为 MB。
|
||||
"""
|
||||
if size_range.find("-") != -1:
|
||||
size_min, size_max = size_range.split("-")
|
||||
return "between", float(size_min.strip()) * _SIZE_UNIT, float(size_max.strip()) * _SIZE_UNIT
|
||||
if size_range.startswith(">"):
|
||||
return "gte", float(size_range[1:].strip()) * _SIZE_UNIT, None
|
||||
if size_range.startswith("<"):
|
||||
return "lte", 0, float(size_range[1:].strip()) * _SIZE_UNIT
|
||||
return "unknown", 0, None
|
||||
|
||||
|
||||
class TorrentHelper:
|
||||
"""
|
||||
种子帮助类
|
||||
@@ -460,52 +495,48 @@ class TorrentHelper:
|
||||
# 包含
|
||||
include = filter_params.get("include")
|
||||
if include:
|
||||
if not re.search(r"%s" % include, content, re.I):
|
||||
if not _filter_pattern_search(include, content):
|
||||
logger.info(f"{content} 不匹配包含规则 {include}")
|
||||
return False
|
||||
# 排除
|
||||
exclude = filter_params.get("exclude")
|
||||
if exclude:
|
||||
if re.search(r"%s" % exclude, content, re.I):
|
||||
if _filter_pattern_search(exclude, content):
|
||||
logger.info(f"{content} 匹配排除规则 {exclude}")
|
||||
return False
|
||||
# 质量
|
||||
quality = filter_params.get("quality")
|
||||
if quality:
|
||||
if not re.search(r"%s" % quality, torrent_info.title, re.I):
|
||||
if not _filter_pattern_search(quality, torrent_info.title):
|
||||
logger.info(f"{torrent_info.title} 不匹配质量规则 {quality}")
|
||||
return False
|
||||
# 分辨率
|
||||
resolution = filter_params.get("resolution")
|
||||
if resolution:
|
||||
if not re.search(r"%s" % resolution, torrent_info.title, re.I):
|
||||
if not _filter_pattern_search(resolution, torrent_info.title):
|
||||
logger.info(f"{torrent_info.title} 不匹配分辨率规则 {resolution}")
|
||||
return False
|
||||
# 特效
|
||||
effect = filter_params.get("effect")
|
||||
if effect:
|
||||
if not re.search(r"%s" % effect, torrent_info.title, re.I):
|
||||
if not _filter_pattern_search(effect, torrent_info.title):
|
||||
logger.info(f"{torrent_info.title} 不匹配特效规则 {effect}")
|
||||
return False
|
||||
|
||||
# 大小
|
||||
size_range = filter_params.get("size")
|
||||
if size_range:
|
||||
if size_range.find("-") != -1:
|
||||
size_rule, size_min, size_max = _parse_filter_size_range(size_range)
|
||||
if size_rule == "between":
|
||||
# 区间
|
||||
size_min, size_max = size_range.split("-")
|
||||
size_min = float(size_min.strip()) * 1024 * 1024
|
||||
size_max = float(size_max.strip()) * 1024 * 1024
|
||||
if torrent_info.size < size_min or torrent_info.size > size_max:
|
||||
return False
|
||||
elif size_range.startswith(">"):
|
||||
elif size_rule == "gte":
|
||||
# 大于
|
||||
size_min = float(size_range[1:].strip()) * 1024 * 1024
|
||||
if torrent_info.size < size_min:
|
||||
return False
|
||||
elif size_range.startswith("<"):
|
||||
elif size_rule == "lte":
|
||||
# 小于
|
||||
size_max = float(size_range[1:].strip()) * 1024 * 1024
|
||||
if torrent_info.size > size_max:
|
||||
return False
|
||||
|
||||
@@ -521,6 +552,7 @@ class TorrentHelper:
|
||||
"""
|
||||
# 匹配季
|
||||
seasons = season_episodes.keys()
|
||||
seasons_set = set(seasons)
|
||||
# 种子季
|
||||
torrent_seasons = meta.season_list
|
||||
if not torrent_seasons:
|
||||
@@ -528,7 +560,7 @@ class TorrentHelper:
|
||||
torrent_seasons = [1]
|
||||
# 种子集
|
||||
torrent_episodes = meta.episode_list
|
||||
if not set(torrent_seasons).issubset(set(seasons)):
|
||||
if not set(torrent_seasons).issubset(seasons_set):
|
||||
# 种子季不在过滤季中
|
||||
logger.debug(
|
||||
f"种子 {torrent.site_name} - {torrent.title} 包含季 {torrent_seasons} 不是需要的季 {list(seasons)}")
|
||||
@@ -539,7 +571,7 @@ class TorrentHelper:
|
||||
if len(torrent_seasons) == 1:
|
||||
need_episodes = season_episodes.get(torrent_seasons[0])
|
||||
if need_episodes \
|
||||
and not set(torrent_episodes).intersection(set(need_episodes)):
|
||||
and not set(torrent_episodes).intersection(need_episodes):
|
||||
# 单季集没有交集的不要
|
||||
logger.debug(f"种子 {torrent.site_name} - {torrent.title} "
|
||||
f"集 {torrent_episodes} 没有需要的集:{need_episodes}")
|
||||
|
||||
Reference in New Issue
Block a user