diff --git a/app/chain/search.py b/app/chain/search.py index 3286f007..c649f88e 100644 --- a/app/chain/search.py +++ b/app/chain/search.py @@ -264,7 +264,9 @@ class SearchChain(ChainBase): meta_info=t[1]) for t in _match_torrents] finally: torrents.clear() + del torrents _match_torrents.clear() + del _match_torrents # 排序 progress.update(value=99, diff --git a/app/chain/subscribe.py b/app/chain/subscribe.py index 9ddff28b..bf1348fb 100644 --- a/app/chain/subscribe.py +++ b/app/chain/subscribe.py @@ -364,32 +364,36 @@ class SubscribeChain(ChainBase): # 过滤搜索结果 matched_contexts = [] - for context in contexts: - if global_vars.is_system_stopped: - break - torrent_meta = context.meta_info - torrent_info = context.torrent_info - torrent_mediainfo = context.media_info + try: + for context in contexts: + if global_vars.is_system_stopped: + break + torrent_meta = context.meta_info + torrent_info = context.torrent_info + torrent_mediainfo = context.media_info - # 洗版 - if subscribe.best_version: - # 洗版时,非整季不要 - if torrent_mediainfo.type == MediaType.TV: - if torrent_meta.episode_list: - logger.info(f'{subscribe.name} 正在洗版,{torrent_info.title} 不是整季') + # 洗版 + if subscribe.best_version: + # 洗版时,非整季不要 + if torrent_mediainfo.type == MediaType.TV: + if torrent_meta.episode_list: + logger.info(f'{subscribe.name} 正在洗版,{torrent_info.title} 不是整季') + continue + # 洗版时,优先级小于等于已下载优先级的不要 + if subscribe.current_priority \ + and torrent_info.pri_order <= subscribe.current_priority: + logger.info( + f'{subscribe.name} 正在洗版,{torrent_info.title} 优先级低于或等于已下载优先级') continue - # 洗版时,优先级小于等于已下载优先级的不要 - if subscribe.current_priority \ - and torrent_info.pri_order <= subscribe.current_priority: - logger.info( - f'{subscribe.name} 正在洗版,{torrent_info.title} 优先级低于或等于已下载优先级') - continue - # 更新订阅自定义属性 - if subscribe.media_category: - torrent_mediainfo.category = subscribe.media_category - if subscribe.episode_group: - torrent_mediainfo.episode_group = subscribe.episode_group - matched_contexts.append(context) + # 更新订阅自定义属性 + if subscribe.media_category: + torrent_mediainfo.category = subscribe.media_category + if subscribe.episode_group: + torrent_mediainfo.episode_group = subscribe.episode_group + matched_contexts.append(context) + finally: + contexts.clear() + del contexts if not matched_contexts: logger.warn(f'订阅 {subscribe.name} 没有符合过滤条件的资源') @@ -432,6 +436,7 @@ class SubscribeChain(ChainBase): logger.debug(f"search Lock released at {datetime.now()}") finally: subscribes.clear() + del subscribes def update_subscribe_priority(self, subscribe: Subscribe, meta: MetaBase, mediainfo: MediaInfo, downloads: Optional[List[Context]]): @@ -552,32 +557,32 @@ class SubscribeChain(ChainBase): return with self._rlock: - try: - logger.debug(f"match lock acquired at {datetime.now()}") + logger.debug(f"match lock acquired at {datetime.now()}") - # 预识别所有未识别的种子 - processed_torrents: Dict[str, List[Context]] = {} - for domain, contexts in torrents.items(): + # 预识别所有未识别的种子 + processed_torrents: Dict[str, List[Context]] = {} + for domain, contexts in torrents.items(): + if global_vars.is_system_stopped: + break + processed_torrents[domain] = [] + for context in contexts: if global_vars.is_system_stopped: break - processed_torrents[domain] = [] - for context in contexts: - if global_vars.is_system_stopped: - break - # 如果种子未识别,尝试识别 - if not context.media_info or (not context.media_info.tmdb_id - and not context.media_info.douban_id): - re_mediainfo = self.recognize_media(meta=context.meta_info) - if re_mediainfo: - # 清理多余信息 - re_mediainfo.clear() - # 更新种子缓存 - context.media_info = re_mediainfo - # 添加已预处理 - processed_torrents[domain].append(context) + # 如果种子未识别,尝试识别 + if not context.media_info or (not context.media_info.tmdb_id + and not context.media_info.douban_id): + re_mediainfo = self.recognize_media(meta=context.meta_info) + if re_mediainfo: + # 清理多余信息 + re_mediainfo.clear() + # 更新种子缓存 + context.media_info = re_mediainfo + # 添加已预处理 + processed_torrents[domain].append(context) - # 所有订阅 - subscribes = SubscribeOper().list(self.get_states_for_search('R')) + # 所有订阅 + subscribes = SubscribeOper().list(self.get_states_for_search('R')) + try: for subscribe in subscribes: if global_vars.is_system_stopped: break @@ -628,155 +633,163 @@ class SubscribeChain(ChainBase): torrenthelper = TorrentHelper() systemconfig = SystemConfigOper() wordsmatcher = WordsMatcher() - for domain, contexts in processed_torrents.items(): - if global_vars.is_system_stopped: - break - if domains and domain not in domains: - continue - logger.debug(f'开始匹配站点:{domain},共缓存了 {len(contexts)} 个种子...') - for context in contexts: + try: + for domain, contexts in processed_torrents.items(): if global_vars.is_system_stopped: break - # 提取信息 - _context = copy.copy(context) - torrent_meta = _context.meta_info - torrent_mediainfo = _context.media_info - torrent_info = _context.torrent_info - - # 不在订阅站点范围的不处理 - sub_sites = self.get_sub_sites(subscribe) - if sub_sites and torrent_info.site not in sub_sites: - logger.debug(f"{torrent_info.site_name} - {torrent_info.title} 不符合订阅站点要求") + if domains and domain not in domains: continue + logger.debug(f'开始匹配站点:{domain},共缓存了 {len(contexts)} 个种子...') + try: + for context in contexts: + if global_vars.is_system_stopped: + break + # 提取信息 + _context = copy.copy(context) + torrent_meta = _context.meta_info + torrent_mediainfo = _context.media_info + torrent_info = _context.torrent_info - # 有自定义识别词时,需要判断是否需要重新识别 - if custom_words_list: - # 使用org_string,应用一次后理论上不能再次应用 - _, apply_words = wordsmatcher.prepare(torrent_meta.org_string, - custom_words=custom_words_list) - if apply_words: - logger.info( - f'{torrent_info.site_name} - {torrent_info.title} 因订阅存在自定义识别词,重新识别元数据...') - # 重新识别元数据 - torrent_meta = MetaInfo(title=torrent_info.title, subtitle=torrent_info.description, - custom_words=custom_words_list) - # 更新元数据缓存 - _context.meta_info = torrent_meta - # 重新识别媒体信息 - torrent_mediainfo = self.recognize_media(meta=torrent_meta, - episode_group=subscribe.episode_group) - if torrent_mediainfo: - # 清理多余信息 - torrent_mediainfo.clear() - # 更新种子缓存 - _context.media_info = torrent_mediainfo - - # 如果仍然没有识别到媒体信息,尝试标题匹配 - if not torrent_mediainfo or (not torrent_mediainfo.tmdb_id and not torrent_mediainfo.douban_id): - logger.info( - f'{torrent_info.site_name} - {torrent_info.title} 重新识别失败,尝试通过标题匹配...') - if torrenthelper.match_torrent(mediainfo=mediainfo, - torrent_meta=torrent_meta, - torrent=torrent_info): - # 匹配成功 - logger.info( - f'{mediainfo.title_year} 通过标题匹配到可选资源:{torrent_info.site_name} - {torrent_info.title}') - torrent_mediainfo = mediainfo - # 更新种子缓存 - _context.media_info = mediainfo - else: - continue - - # 直接比对媒体信息 - if torrent_mediainfo and (torrent_mediainfo.tmdb_id or torrent_mediainfo.douban_id): - if torrent_mediainfo.type != mediainfo.type: - continue - if torrent_mediainfo.tmdb_id \ - and torrent_mediainfo.tmdb_id != mediainfo.tmdb_id: - continue - if torrent_mediainfo.douban_id \ - and torrent_mediainfo.douban_id != mediainfo.douban_id: - continue - logger.info( - f'{mediainfo.title_year} 通过媒体信ID匹配到可选资源:{torrent_info.site_name} - {torrent_info.title}') - else: - continue - - # 如果是电视剧 - if torrent_mediainfo.type == MediaType.TV: - # 有多季的不要 - if len(torrent_meta.season_list) > 1: - logger.debug(f'{torrent_info.title} 有多季,不处理') - continue - # 比对季 - if torrent_meta.begin_season: - if meta.begin_season != torrent_meta.begin_season: - logger.debug(f'{torrent_info.title} 季不匹配') + # 不在订阅站点范围的不处理 + sub_sites = self.get_sub_sites(subscribe) + if sub_sites and torrent_info.site not in sub_sites: + logger.debug(f"{torrent_info.site_name} - {torrent_info.title} 不符合订阅站点要求") continue - elif meta.begin_season != 1: - logger.debug(f'{torrent_info.title} 季不匹配') - continue - # 非洗版 - if not subscribe.best_version: - # 不是缺失的剧集不要 - if no_exists and no_exists.get(mediakey): - # 缺失集 - no_exists_info = no_exists.get(mediakey).get(subscribe.season) - if no_exists_info: - # 是否有交集 - if no_exists_info.episodes and \ - torrent_meta.episode_list and \ - not set(no_exists_info.episodes).intersection( - set(torrent_meta.episode_list) - ): - logger.debug( - f'{torrent_info.title} 对应剧集 {torrent_meta.episode_list} 未包含缺失的剧集' - ) - continue - else: - # 洗版时,非整季不要 - if meta.type == MediaType.TV: - if torrent_meta.episode_list: - logger.debug(f'{subscribe.name} 正在洗版,{torrent_info.title} 不是整季') + + # 有自定义识别词时,需要判断是否需要重新识别 + if custom_words_list: + # 使用org_string,应用一次后理论上不能再次应用 + _, apply_words = wordsmatcher.prepare(torrent_meta.org_string, + custom_words=custom_words_list) + if apply_words: + logger.info( + f'{torrent_info.site_name} - {torrent_info.title} 因订阅存在自定义识别词,重新识别元数据...') + # 重新识别元数据 + torrent_meta = MetaInfo(title=torrent_info.title, subtitle=torrent_info.description, + custom_words=custom_words_list) + # 更新元数据缓存 + _context.meta_info = torrent_meta + # 重新识别媒体信息 + torrent_mediainfo = self.recognize_media(meta=torrent_meta, + episode_group=subscribe.episode_group) + if torrent_mediainfo: + # 清理多余信息 + torrent_mediainfo.clear() + # 更新种子缓存 + _context.media_info = torrent_mediainfo + + # 如果仍然没有识别到媒体信息,尝试标题匹配 + if not torrent_mediainfo or (not torrent_mediainfo.tmdb_id and not torrent_mediainfo.douban_id): + logger.info( + f'{torrent_info.site_name} - {torrent_info.title} 重新识别失败,尝试通过标题匹配...') + if torrenthelper.match_torrent(mediainfo=mediainfo, + torrent_meta=torrent_meta, + torrent=torrent_info): + # 匹配成功 + logger.info( + f'{mediainfo.title_year} 通过标题匹配到可选资源:{torrent_info.site_name} - {torrent_info.title}') + torrent_mediainfo = mediainfo + # 更新种子缓存 + _context.media_info = mediainfo + else: continue - # 匹配订阅附加参数 - if not torrenthelper.filter_torrent(torrent_info=torrent_info, - filter_params=self.get_params(subscribe)): - continue + # 直接比对媒体信息 + if torrent_mediainfo and (torrent_mediainfo.tmdb_id or torrent_mediainfo.douban_id): + if torrent_mediainfo.type != mediainfo.type: + continue + if torrent_mediainfo.tmdb_id \ + and torrent_mediainfo.tmdb_id != mediainfo.tmdb_id: + continue + if torrent_mediainfo.douban_id \ + and torrent_mediainfo.douban_id != mediainfo.douban_id: + continue + logger.info( + f'{mediainfo.title_year} 通过媒体信ID匹配到可选资源:{torrent_info.site_name} - {torrent_info.title}') + else: + continue - # 优先级过滤规则 - if subscribe.best_version: - rule_groups = subscribe.filter_groups \ - or systemconfig.get(SystemConfigKey.BestVersionFilterRuleGroups) - else: - rule_groups = subscribe.filter_groups \ - or systemconfig.get(SystemConfigKey.SubscribeFilterRuleGroups) - result: List[TorrentInfo] = self.filter_torrents( - rule_groups=rule_groups, - torrent_list=[torrent_info], - mediainfo=torrent_mediainfo) - if result is not None and not result: - # 不符合过滤规则 - logger.debug(f"{torrent_info.title} 不匹配过滤规则") - continue + # 如果是电视剧 + if torrent_mediainfo.type == MediaType.TV: + # 有多季的不要 + if len(torrent_meta.season_list) > 1: + logger.debug(f'{torrent_info.title} 有多季,不处理') + continue + # 比对季 + if torrent_meta.begin_season: + if meta.begin_season != torrent_meta.begin_season: + logger.debug(f'{torrent_info.title} 季不匹配') + continue + elif meta.begin_season != 1: + logger.debug(f'{torrent_info.title} 季不匹配') + continue + # 非洗版 + if not subscribe.best_version: + # 不是缺失的剧集不要 + if no_exists and no_exists.get(mediakey): + # 缺失集 + no_exists_info = no_exists.get(mediakey).get(subscribe.season) + if no_exists_info: + # 是否有交集 + if no_exists_info.episodes and \ + torrent_meta.episode_list and \ + not set(no_exists_info.episodes).intersection( + set(torrent_meta.episode_list) + ): + logger.debug( + f'{torrent_info.title} 对应剧集 {torrent_meta.episode_list} 未包含缺失的剧集' + ) + continue + else: + # 洗版时,非整季不要 + if meta.type == MediaType.TV: + if torrent_meta.episode_list: + logger.debug(f'{subscribe.name} 正在洗版,{torrent_info.title} 不是整季') + continue - # 洗版时,优先级小于已下载优先级的不要 - if subscribe.best_version: - if subscribe.current_priority \ - and torrent_info.pri_order <= subscribe.current_priority: - logger.info( - f'{subscribe.name} 正在洗版,{torrent_info.title} 优先级低于或等于已下载优先级') - continue + # 匹配订阅附加参数 + if not torrenthelper.filter_torrent(torrent_info=torrent_info, + filter_params=self.get_params(subscribe)): + continue - # 匹配成功 - logger.info(f'{mediainfo.title_year} 匹配成功:{torrent_info.title}') - # 自定义属性 - if subscribe.media_category: - torrent_mediainfo.category = subscribe.media_category - if subscribe.episode_group: - torrent_mediainfo.episode_group = subscribe.episode_group - _match_context.append(_context) + # 优先级过滤规则 + if subscribe.best_version: + rule_groups = subscribe.filter_groups \ + or systemconfig.get(SystemConfigKey.BestVersionFilterRuleGroups) + else: + rule_groups = subscribe.filter_groups \ + or systemconfig.get(SystemConfigKey.SubscribeFilterRuleGroups) + result: List[TorrentInfo] = self.filter_torrents( + rule_groups=rule_groups, + torrent_list=[torrent_info], + mediainfo=torrent_mediainfo) + if result is not None and not result: + # 不符合过滤规则 + logger.debug(f"{torrent_info.title} 不匹配过滤规则") + continue + + # 洗版时,优先级小于已下载优先级的不要 + if subscribe.best_version: + if subscribe.current_priority \ + and torrent_info.pri_order <= subscribe.current_priority: + logger.info( + f'{subscribe.name} 正在洗版,{torrent_info.title} 优先级低于或等于已下载优先级') + continue + + # 匹配成功 + logger.info(f'{mediainfo.title_year} 匹配成功:{torrent_info.title}') + # 自定义属性 + if subscribe.media_category: + torrent_mediainfo.category = subscribe.media_category + if subscribe.episode_group: + torrent_mediainfo.episode_group = subscribe.episode_group + _match_context.append(_context) + finally: + contexts.clear() + del contexts + finally: + processed_torrents.clear() + del processed_torrents if not _match_context: # 未匹配到资源 @@ -802,11 +815,11 @@ class SubscribeChain(ChainBase): if subscribe: self.finish_subscribe_or_not(subscribe=subscribe, meta=meta, mediainfo=mediainfo, downloads=downloads, lefts=lefts) - - logger.debug(f"match Lock released at {datetime.now()}") finally: subscribes.clear() - processed_torrents.clear() + del subscribes + + logger.debug(f"match Lock released at {datetime.now()}") def check(self): """ diff --git a/app/chain/torrents.py b/app/chain/torrents.py index e3902336..d08be754 100644 --- a/app/chain/torrents.py +++ b/app/chain/torrents.py @@ -131,6 +131,7 @@ class TorrentsChain(ChainBase): ret_torrents.append(torrentinfo) finally: rss_items.clear() + del rss_items return ret_torrents def refresh(self, stype: Optional[str] = None, sites: List[int] = None) -> Dict[str, List[Context]]: @@ -220,6 +221,7 @@ class TorrentsChain(ChainBase): torrents_cache[domain] = torrents_cache[domain][-settings.CONF["torrents"]:] finally: torrents.clear() + del torrents else: logger.info(f'{indexer.get("name")} 没有获取到种子') diff --git a/app/chain/transfer.py b/app/chain/transfer.py index 1977da9f..82d867ad 100755 --- a/app/chain/transfer.py +++ b/app/chain/transfer.py @@ -864,6 +864,7 @@ class TransferChain(ChainBase, metaclass=Singleton): self.transfer_completed(hashs=torrent.hash, downloader=torrent.downloader) finally: torrents.clear() + del torrents # 结束 logger.info("所有下载器中下载完成的文件已整理完成") @@ -1144,6 +1145,7 @@ class TransferChain(ChainBase, metaclass=Singleton): transfer_tasks.append(transfer_task) finally: file_items.clear() + del file_items # 实时整理 if transfer_tasks: @@ -1187,6 +1189,7 @@ class TransferChain(ChainBase, metaclass=Singleton): processed_num += 1 finally: transfer_tasks.clear() + del transfer_tasks # 整理结束 __end_msg = f"整理队列处理完成,共整理 {total_num} 个文件,失败 {fail_num} 个" diff --git a/app/modules/qbittorrent/__init__.py b/app/modules/qbittorrent/__init__.py index 85177f00..c0af0029 100644 --- a/app/modules/qbittorrent/__init__.py +++ b/app/modules/qbittorrent/__init__.py @@ -182,6 +182,7 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]): return downloader or self.get_default_config_name(), torrent_hash, torrent_layout, f"下载任务已存在" finally: torrents.clear() + del torrents return None, None, None, f"添加种子任务失败:{content}" else: # 获取种子Hash @@ -211,6 +212,7 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]): sucess_epidised = list(set(sucess_epidised).union(set(meta_info.episode_list))) finally: torrent_files.clear() + del torrent_files if sucess_epidised and file_ids: # 选择文件 server.set_files(torrent_hash=torrent_hash, file_ids=file_ids, priority=0) @@ -269,6 +271,7 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]): )) finally: torrents.clear() + del torrents elif status == TorrentStatus.TRANSFER: # 获取已完成且未整理的 for name, server in servers.items(): @@ -293,6 +296,7 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]): )) finally: torrents.clear() + del torrents elif status == TorrentStatus.DOWNLOADING: # 获取正在下载的任务 for name, server in servers.items(): @@ -319,6 +323,7 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]): )) finally: torrents.clear() + del torrents else: return None return ret_torrents # noqa diff --git a/app/modules/qbittorrent/qbittorrent.py b/app/modules/qbittorrent/qbittorrent.py index dd2a8e0c..2e538963 100644 --- a/app/modules/qbittorrent/qbittorrent.py +++ b/app/modules/qbittorrent/qbittorrent.py @@ -105,6 +105,7 @@ class Qbittorrent: results.append(torrent) finally: torrents.clear() + del torrents return results, False return torrents or [], False except Exception as err: diff --git a/app/modules/transmission/__init__.py b/app/modules/transmission/__init__.py index 1ded1222..0572a86e 100644 --- a/app/modules/transmission/__init__.py +++ b/app/modules/transmission/__init__.py @@ -184,6 +184,7 @@ class TransmissionModule(_ModuleBase, _DownloaderBase[Transmission]): return downloader or self.get_default_config_name(), torrent_hash, torrent_layout, f"下载任务已存在" finally: torrents.clear() + del torrents return None, None, None, f"添加种子任务失败:{content}" else: torrent_hash = torrent.hashString @@ -215,6 +216,7 @@ class TransmissionModule(_ModuleBase, _DownloaderBase[Transmission]): server.start_torrents(torrent_hash) finally: torrent_files.clear() + del torrent_files return downloader or self.get_default_config_name(), torrent_hash, torrent_layout, "添加下载任务成功" else: return downloader or self.get_default_config_name(), torrent_hash, torrent_layout, "添加下载任务成功" @@ -255,6 +257,7 @@ class TransmissionModule(_ModuleBase, _DownloaderBase[Transmission]): )) finally: torrents.clear() + del torrents elif status == TorrentStatus.TRANSFER: # 获取已完成且未整理的 for name, server in servers.items(): @@ -281,6 +284,7 @@ class TransmissionModule(_ModuleBase, _DownloaderBase[Transmission]): )) finally: torrents.clear() + del torrents elif status == TorrentStatus.DOWNLOADING: # 获取正在下载的任务 for name, server in servers.items(): @@ -306,6 +310,7 @@ class TransmissionModule(_ModuleBase, _DownloaderBase[Transmission]): )) finally: torrents.clear() + del torrents else: return None return ret_torrents # noqa diff --git a/app/modules/transmission/transmission.py b/app/modules/transmission/transmission.py index 0ce9f8ef..564a55a9 100755 --- a/app/modules/transmission/transmission.py +++ b/app/modules/transmission/transmission.py @@ -106,6 +106,7 @@ class Transmission: ret_torrents.append(torrent) finally: torrents.clear() + del torrents return ret_torrents, False def get_completed_torrents(self, ids: Union[str, list] = None,