"""领域模型 - 纯数据结构,不依赖任何框架""" from dataclasses import dataclass, field from datetime import datetime from typing import List, Optional @dataclass class ProxyRaw: """爬虫爬取的原始代理数据""" ip: str port: int protocol: str = "http" def __post_init__(self): self.protocol = self.protocol.lower().strip() if self.protocol not in ("http", "https", "socks4", "socks5"): self.protocol = "http" if not isinstance(self.port, int) or not (1 <= self.port <= 65535): raise ValueError(f"port must be between 1 and 65535, got {self.port}") @dataclass class Proxy: """数据库中的代理实体""" ip: str port: int protocol: str score: int response_time_ms: Optional[float] = None last_check: Optional[datetime] = None created_at: Optional[datetime] = None @dataclass class PluginInfo: """插件元数据""" id: str name: str display_name: str description: str enabled: bool last_run: Optional[datetime] = None success_count: int = 0 failure_count: int = 0 @dataclass class CrawlResult: """插件爬取结果""" plugin_name: str proxies: List[ProxyRaw] = field(default_factory=list) success_count: int = 0 failure_count: int = 0 error: Optional[str] = None