Files
ProxyPool/core/plugin_manager.py
2026-01-27 21:17:36 +08:00

126 lines
4.8 KiB
Python

import os
import importlib
import inspect
import asyncio
from typing import List, Dict, Optional
from core.crawler import BasePlugin
from core.log import logger
class PluginManager:
def __init__(self, plugin_dir='plugins'):
self.plugin_dir = plugin_dir
self.plugins = []
self.plugin_stats = {}
self._load_plugins()
self._init_stats()
def _init_stats(self):
for plugin in self.plugins:
self.plugin_stats[plugin.name] = {
'success_count': 0,
'failure_count': 0,
'last_run': None
}
def _load_plugins(self):
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
full_plugin_path = os.path.join(base_dir, self.plugin_dir)
if not os.path.exists(full_plugin_path):
logger.error(f"插件目录不存在: {full_plugin_path}")
return
for filename in os.listdir(full_plugin_path):
if filename.endswith('.py') and not filename.startswith('__'):
module_name = f"{self.plugin_dir}.{filename[:-3]}"
try:
module = importlib.import_module(module_name)
for name, obj in inspect.getmembers(module):
if inspect.isclass(obj) and issubclass(obj, BasePlugin) and obj is not BasePlugin:
plugin_instance = obj()
if plugin_instance.enabled:
logger.info(f"成功加载插件: {name} 来自 {module_name}")
self.plugins.append(plugin_instance)
else:
logger.info(f"插件已禁用,跳过加载: {name} 来自 {module_name}")
except Exception as e:
logger.error(f"加载插件失败 {module_name}: {e}")
def get_plugin_by_name(self, plugin_name: str) -> Optional[BasePlugin]:
for plugin in self.plugins:
if plugin.name == plugin_name:
return plugin
return None
def get_all_plugin_info(self) -> List[Dict]:
plugins_info = []
for plugin in self.plugins:
stats = self.plugin_stats.get(plugin.name, {
'success_count': 0,
'failure_count': 0,
'last_run': None
})
plugins_info.append({
'id': plugin.name,
'name': plugin.name,
'enabled': plugin.enabled,
'description': getattr(plugin, 'description', f'{plugin.name}网站爬取代理'),
'last_run': stats['last_run'],
'success_count': stats['success_count'],
'failure_count': stats['failure_count']
})
return plugins_info
def toggle_plugin(self, plugin_name: str, enabled: bool) -> bool:
plugin = self.get_plugin_by_name(plugin_name)
if plugin:
plugin.enabled = enabled
logger.info(f"插件 {plugin_name}{'启用' if enabled else '禁用'}")
return True
return False
async def run_plugin(self, plugin_name: str):
plugin = self.get_plugin_by_name(plugin_name)
if not plugin:
logger.error(f"插件不存在: {plugin_name}")
return []
if not plugin.enabled:
logger.warning(f"插件已禁用: {plugin_name}")
return []
try:
results = await plugin.run()
success_count = len(results)
failure_count = 0
from datetime import datetime
self.plugin_stats[plugin.name] = {
'success_count': self.plugin_stats[plugin.name]['success_count'] + success_count,
'failure_count': self.plugin_stats[plugin.name]['failure_count'] + failure_count,
'last_run': datetime.now().isoformat()
}
logger.info(f"插件 {plugin_name} 执行完成,成功: {success_count}")
return results
except Exception as e:
logger.error(f"插件 {plugin_name} 执行失败: {e}")
from datetime import datetime
self.plugin_stats[plugin.name] = {
'success_count': self.plugin_stats[plugin.name]['success_count'],
'failure_count': self.plugin_stats[plugin.name]['failure_count'] + 1,
'last_run': datetime.now().isoformat()
}
return []
async def run_all(self):
"""并发运行所有插件"""
tasks = [plugin.run() for plugin in self.plugins]
# 并发执行并收集结果
results_list = await asyncio.gather(*tasks)
# 将嵌套列表扁平化并产出结果
for results in results_list:
for proxy in results:
yield proxy