This repository has been archived on 2026-08-07. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
kb-skills/.planning/research/STACK.md
T
starmen1265 2561de6ad7
PR Test / lint (pull_request) Successful in 2s
docs: update research for v1.3 anti-crawler optimization
- 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>
2026-03-18 20:45:14 +08:00

13 KiB

Stack Research

Domain: Skill-based Workflow Orchestration System (Python) Researched: 2026-03-18 (Updated for v1.3 Anti-Crawler) Confidence: HIGH

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)

Anti-Crawler (HIGH confidence)

Comparisons (MEDIUM confidence)


Stack research for: Skill-based Workflow Orchestration System Researched: 2026-03-13, Updated: 2026-03-18 for v1.3 Anti-Crawler