This commit is contained in:
2025-11-28 21:20:40 +08:00
commit f940b95b67
73 changed files with 15721 additions and 0 deletions

87
parsers/factory.py Normal file
View File

@@ -0,0 +1,87 @@
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("无法识别的视频平台")