init
This commit is contained in:
87
parsers/factory.py
Normal file
87
parsers/factory.py
Normal 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("无法识别的视频平台")
|
||||
Reference in New Issue
Block a user