2561de6ad7
PR Test / lint (pull_request) Successful in 2s
- Add architecture research for proxy pool, behavior camouflage, captcha detection, and error recovery - Update features, pitfalls, and stack documentation - Add phase 10 validation checklist Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
13 KiB
13 KiB
Stack Research
Domain: Skill-based Workflow Orchestration System (Python) Researched: 2026-03-18 (Updated for v1.3 Anti-Crawler) Confidence: HIGH
Recommended Stack
Core Technologies
| Technology | Version | Purpose | Why Recommended |
|---|---|---|---|
| Python | 3.12+ | Runtime | 项目已使用,3.12 提供更好的性能和错误消息;类型提示增强;f-string 改进 |
| Pydantic | 2.11+ | 数据验证 & Schema | v2.11+ 提供更快的解析速度、更低的内存占用;原生支持 JSON Schema 生成;与项目 PIPE-07 需求完美匹配 |
| pydantic-settings | 2.8+ | 配置管理 | Pydantic 官方配置方案;支持环境变量、.env 文件、类型安全;解决现有 ~/.kb_env 分散配置问题 |
| transitions | 0.9.3+ | 状态机 | 轻量级、面向对象的状态机实现;支持回调、条件转换、嵌套状态;无需数据库,适合步骤级状态管理 |
| Typer | 0.15+ | CLI 框架 | 基于 Click 的现代 CLI 库;利用 Python 类型提示自动生成参数;比 argparse 更简洁,比 Click 更现代 |
| Rich | 14.1+ | 终端输出美化 | 提供彩色输出、进度条、表格;与 Typer 无缝集成;改善 CLI 用户体验 |
v1.3 Anti-Crawler Libraries (NEW)
| Library | Version | Purpose | Why Recommended |
|---|---|---|---|
| aiolimiter | 1.2.1 | asyncio 限流 | 实现 Leaky Bucket 算法;与现有 asyncio 架构完美配合;零依赖;比手动 sleep 更精确控制请求速率 |
| playwright-stealth | 2.0.2 | 浏览器指纹伪装 | 隐藏 Playwright 自动化特征;防止 webdriver 检测;简单易用(一行代码集成);与现有 Playwright 代码兼容 |
| camoufox | 0.4.11 | 高级反指纹 (Phase 2) | 基于 Firefox 的反检测浏览器;比 playwright-stealth 更强;适合知乎/B站高安全场景;可选依赖 |
Supporting Libraries
| Library | Version | Purpose | When to Use |
|---|---|---|---|
| httpx | 0.28+ | 异步 HTTP 客户端 | 现有项目已使用;替代 requests 用于需要异步的场景 |
| tenacity | 8.5+ | 重试机制 | 实现错误恢复策略 (PIPE-05);支持指数退避、条件重试;v1.3 增强:添加 wait_random 抖动 |
| python-dotenv | 1.0+ | .env 文件加载 | 与 pydantic-settings 配合;可选,pydantic-settings 已内置支持 |
| loguru | 0.7+ | 日志 | 替代 stdlib logging;更简洁的 API;内置旋转、压缩、格式化 |
| Playwright | 1.50+ | 浏览器自动化 | 现有项目已使用;支持代理、API 拦截、隐身模式 |
Development Tools
| Tool | Purpose | Notes |
|---|---|---|
| uv | 依赖管理 | 10-100x 快于 pip;兼容 pyproject.toml;支持 lockfile |
| pytest | 8.3+ | 测试框架 |
| ruff | 0.9+ | Linter + Formatter |
Installation
# Core dependencies
uv add pydantic pydantic-settings transitions typer rich
# Supporting dependencies
uv add httpx tenacity loguru
# v1.3 Anti-Crawler (NEW)
uv add aiolimiter playwright-stealth
# v1.3 Optional: Advanced anti-fingerprinting (Phase 2)
uv add camoufox # 仅在 playwright-stealth 不足时使用
# Dev dependencies
uv add --dev pytest pytest-cov ruff
Alternatives Considered
Anti-Crawler Alternatives
| Recommended | Alternative | Why Not |
|---|---|---|
| aiolimiter | asyncio.sleep | 手动 sleep 不精确;无法应对并发场景;无速率保证 |
| aiolimiter | ratelimit 库 | 仅支持同步;不支持 asyncio |
| aiolimiter | aiometer | 功能过多(并发限制、批处理);项目只需速率限制 |
| playwright-stealth | undetected-chromedriver | 仅支持 Selenium;需要 Chrome;与 Playwright 不兼容 |
| playwright-stealth | puppeteer-stealth | JavaScript 生态;不适用于 Python |
| camoufox | Selenium Wire | 过于底层;需要手动配置代理和请求修改 |
| 自定义 ProxyPool | rotating-proxy 库 | 代码质量差;维护不活跃;不支持自定义代理源 |
| 自定义 ProxyPool | scrapy-rotating-proxies | 与 Scrapy 绑定;不适用于 Playwright |
| CAPTCHA 检测 + 告警 | 2captcha / YesCaptcha | PROJECT.md 明确排除付费打码服务 |
| CAPTCHA 检测 + 告警 | ddddocr | OCR 识别率不稳定;验证码类型多变 |
General Alternatives
| Recommended | Alternative | When to Use Alternative |
|---|---|---|
| transitions | Prefect 3.0 | 当需要分布式执行、复杂 DAG、Web UI 监控时。但对于本项目的轻量级单机管道,Prefect 过于重量级 |
| transitions | Dagster | 当需要数据资产血缘追踪、强类型管道定义时。学习曲线较陡 |
| transitions | 纯 JSON 状态 | 当状态极其简单且不需要状态机特性时。但会失去转换验证、回调等安全特性 |
| Typer | Click | 当需要更底层的控制或 Typer 的类型推断有问题时。Typer 底层就是 Click |
| Pydantic | jsonschema 库 | 当需要验证外部 JSON Schema 且不关心 Python 对象映射时。Pydantic 更 Pythonic |
| uv | Poetry | 当团队已熟悉 Poetry 工作流时。但 uv 更快且兼容性更好 |
What NOT to Use
| Avoid | Why | Use Instead |
|---|---|---|
| Airflow | 需要数据库后端;DAG 定义繁琐;过度工程化 | transitions + 简单状态文件 |
| Celery | 需要 message broker;面向任务队列而非工作流编排 | transitions(状态机模式) |
| argparse | 样板代码多;无自动帮助生成 | Typer |
| dataclasses | 无运行时验证;无 JSON Schema 支持 | Pydantic BaseModel |
| requests | 同步阻塞;httpx 提供同步+异步统一 API | httpx |
| logging (stdlib) | 配置繁琐;API 不友好 | loguru |
| rotating-proxy | 代码质量差;2020年后无更新;不支持自定义源 | 自定义 ProxyPoolConfig |
| scrapy-rotating-proxies | 与 Scrapy 紧密绑定 | 自定义 ProxyPoolConfig |
| 2captcha/YesCaptcha | 付费服务;PROJECT.md 明确排除 | CAPTCHA 检测 + 告警 + 暂停 |
| ddddocr | 识别率不稳定;维护不活跃 | CAPTCHA 检测 + 告警 |
Stack Patterns by Variant
If 需要持久化工作流状态到数据库:
- 添加 SQLAlchemy 2.0+ 作为 ORM
- 配合 alembic 做迁移
- 因为: transitions 状态可以序列化到数据库
If 需要并发处理多个链接:
- 使用 asyncio + httpx 异步模式
- 配合 transitions 的 AsyncMachine 扩展
- 因为: 提高吞吐量而不增加复杂度
If 需要可视化工作流状态:
- 使用 transitions 的 GraphMachine 扩展
- 生成 Mermaid 或 Graphviz 图表
- 因为: 内置支持,无需额外工具
If playwright-stealth 被检测 (Phase 2):
- 切换到 camoufox
- 配合现有的代理配置
- 因为: Firefox 内核更难被指纹识别
Version Compatibility
| Package A | Compatible With | Notes |
|---|---|---|
| pydantic 2.11+ | pydantic-settings 2.8+ | 同一组织维护,版本同步更新 |
| typer 0.15+ | rich 14.1+ | Typer 内置 Rich 集成 |
| transitions 0.9.3+ | Python 3.12+ | 支持 Python 3.13 |
| aiolimiter 1.2.1 | asyncio | 零外部依赖,纯 Python |
| playwright-stealth 2.0.2 | Playwright 1.40+ | 已测试兼容 |
| camoufox 0.4.11 | Python 3.10+ | 支持 Python 3.12+ |
Example Architecture
工作流状态 Schema
from pydantic import BaseModel
from enum import Enum
from datetime import datetime
class StepStatus(str, Enum):
PENDING = "pending"
RUNNING = "running"
SUCCESS = "success"
SKIPPED = "skipped"
FAILED = "failed"
class WorkflowState(BaseModel):
link: str
current_step: str
step_status: dict[str, StepStatus] # 步骤名 -> 状态
artifacts: dict[str, str] # 步骤名 -> 输出文件路径
errors: list[str] # 错误历史
created_at: datetime
updated_at: datetime
管道步骤 Schema 设计
from pydantic import BaseModel
from typing import Literal
class StepInput(BaseModel):
link: str
work_dir: str
# 通用字段...
class StepOutput(BaseModel):
status: Literal["success", "skipped", "failed"]
artifacts: dict[str, str] # 输出文件路径
error: str | None = None
CLI 入口设计
import typer
from rich.console import Console
app = typer.Typer()
console = Console()
@app.command()
def process(link: str, resume: bool = False):
"""处理单个链接"""
# transitions 状态机驱动
v1.3 Anti-Crawler 集成示例
aiolimiter 限流
from aiolimiter import AsyncLimiter
import asyncio
# 10 请求/分钟 = 1 请求/6秒
limiter = AsyncLimiter(10, 60)
async def fetch_with_rate_limit(url: str):
async with limiter:
# 请求会被自动限流
return await httpx_client.get(url)
playwright-stealth 集成
from playwright.sync_api import sync_playwright
from playwright_stealth import stealth_sync
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
# 应用隐身补丁
stealth_sync(page)
# 正常使用,检测不到 webdriver
page.goto("https://www.zhihu.com")
tenacity 抖动增强
from tenacity import retry, stop_after_attempt, wait_exponential, wait_random
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=2, max=10) + wait_random(0, 1),
reraise=True
)
async def fetch_with_jitter(url: str):
# 指数退避 + 随机抖动,避免请求同步
return await httpx_client.get(url)
代理池配置
from pydantic import BaseModel
from typing import Optional
import random
class ProxyPoolConfig(BaseModel):
"""代理池配置"""
proxies: list[str] # ["http://ip:port", ...]
strategy: str = "round_robin" # round_robin | random
def get_next_proxy(self) -> Optional[str]:
if not self.proxies:
return None
if self.strategy == "random":
return random.choice(self.proxies)
# round_robin
proxy = self.proxies.pop(0)
self.proxies.append(proxy)
return proxy
CAPTCHA 检测
from dataclasses import dataclass
from enum import Enum
class CaptchaType(str, Enum):
SLIDER = "slider" # 滑块验证码
CLICK = "click" # 点选验证码
TEXT = "text" # 文字验证码
UNKNOWN = "unknown"
@dataclass
class CaptchaDetection:
detected: bool
captcha_type: CaptchaType
confidence: float # 0.0 - 1.0
def detect_captcha(page_content: str) -> CaptchaDetection:
"""检测页面是否包含验证码"""
captcha_indicators = [
("滑块", CaptchaType.SLIDER),
("验证码", CaptchaType.UNKNOWN),
("geetest", CaptchaType.SLIDER),
("点击", CaptchaType.CLICK),
]
for indicator, captcha_type in captcha_indicators:
if indicator in page_content:
return CaptchaDetection(
detected=True,
captcha_type=captcha_type,
confidence=0.8
)
return CaptchaDetection(detected=False, captcha_type=CaptchaType.UNKNOWN, confidence=0.0)
Sources
Core Stack (HIGH confidence)
- Pydantic v2.11 Release — 版本特性确认
- Pydantic JSON Schema Docs — JSON Schema 生成能力
- transitions 0.9.3 on PyPI — 状态机库详情
- uv Official Docs — 包管理器最佳实践
Anti-Crawler (HIGH confidence)
- aiolimiter on PyPI — asyncio 限流库
- aiolimiter GitHub — 文档和示例
- playwright-stealth on PyPI — 浏览器隐身库
- playwright-stealth GitHub — 源码和使用指南
- camoufox on PyPI — Firefox 反检测浏览器
- camoufox GitHub — 文档和配置选项
Comparisons (MEDIUM confidence)
- Prefect vs Dagster Comparison — 编排工具对比
- Python CLI Tools Comparison 2025 — CLI 框架对比
- pydantic-settings Guide — 配置管理方案
- tenacity wait_random documentation — 抖动策略
Stack research for: Skill-based Workflow Orchestration System Researched: 2026-03-13, Updated: 2026-03-18 for v1.3 Anti-Crawler