from parsers.douyin import DouyinParser from parsers.tiktok import TikTokParser from parsers.bilibili import BilibiliMirParser, BilibiliBugPKParser, BilibiliYaohuParser from models import ParserAPI import random class ParserFactory: """解析器工厂类""" @staticmethod def create_parser(api_config: ParserAPI): """根据API配置创建解析器实例""" platform = api_config.platform.lower() api_url = api_config.api_url api_key = api_config.api_key if platform == 'douyin': return DouyinParser(api_url, api_key) elif platform == 'tiktok': return TikTokParser(api_url, api_key) elif platform == 'bilibili': # 根据API名称选择不同的解析器 if 'mir6' in api_url: return BilibiliMirParser(api_url, api_key) elif 'bugpk' in api_url: return BilibiliBugPKParser(api_url, api_key) elif 'yaohud' in api_url: return BilibiliYaohuParser(api_url, api_key) else: return BilibiliMirParser(api_url, api_key) else: raise ValueError(f"不支持的平台: {platform}") @staticmethod def get_parser_for_platform(platform: str): """获取指定平台的解析器(带负载均衡)""" from models import db # 查询该平台所有启用且健康的API apis = ParserAPI.query.filter_by( platform=platform.lower(), is_enabled=True, health_status=True ).all() if not apis: raise Exception(f"没有可用的{platform}解析接口") # 如果是哔哩哔哩,使用加权随机选择(负载均衡) if platform.lower() == 'bilibili' and len(apis) > 1: api = ParserFactory._weighted_random_choice(apis) else: # 其他平台选择第一个可用的 api = apis[0] return ParserFactory.create_parser(api), api @staticmethod def _weighted_random_choice(apis): """加权随机选择""" total_weight = sum(api.weight for api in apis) if total_weight == 0: return random.choice(apis) rand = random.uniform(0, total_weight) current = 0 for api in apis: current += api.weight if rand <= current: return api return apis[-1] @staticmethod def detect_platform(video_url: str) -> str: """检测视频链接所属平台""" url_lower = video_url.lower() if 'douyin.com' in url_lower or 'v.douyin' in url_lower: return 'douyin' elif 'tiktok.com' in url_lower: return 'tiktok' elif 'bilibili.com' in url_lower or 'b23.tv' in url_lower: return 'bilibili' else: raise ValueError("无法识别的视频平台")