"""抓取配置加载器。 从 YAML 文件读取 sources.yaml,并校验为 CrawlerConfig。 """ from __future__ import annotations from pathlib import Path from typing import Any import yaml from loguru import logger from .models import CrawlerConfig DEFAULT_CONFIG_PATH = Path("configs/sources.yaml") def load_crawler_config(path: str | Path | None = None) -> CrawlerConfig: """加载并校验抓取配置。 参数: path: YAML 配置路径,默认 configs/sources.yaml。 返回: CrawlerConfig 实例。 异常: FileNotFoundError: 配置文件不存在。 ValueError: YAML 顶层不是 mapping 或 sources 缺失。 pydantic.ValidationError: schema 校验失败。 """ config_path = Path(path) if path else DEFAULT_CONFIG_PATH if not config_path.is_file(): raise FileNotFoundError(f"抓取配置文件不存在: {config_path}") with config_path.open("r", encoding="utf-8") as f: raw: Any = yaml.safe_load(f) if not isinstance(raw, dict): raise ValueError(f"配置文件顶层必须是 mapping,实际类型: {type(raw).__name__}") if "sources" not in raw: raise ValueError("配置文件缺少 sources 字段") config = CrawlerConfig.model_validate(raw) logger.info( "已加载抓取配置: 总 {} 个源, 启用 {} 个, 并发上限 {}", len(config.sources), len(config.enabled_sources()), config.settings.concurrency, ) return config