88 lines
2.9 KiB
Python
88 lines
2.9 KiB
Python
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("无法识别的视频平台")
|