diff --git a/.planning/phases/10-proxy-pool/10-RESEARCH.md b/.planning/phases/10-proxy-pool/10-RESEARCH.md
new file mode 100644
index 0000000..15bbd99
--- /dev/null
+++ b/.planning/phases/10-proxy-pool/10-RESEARCH.md
@@ -0,0 +1,599 @@
+# Phase 10: Proxy Pool (代理池管理) - Research
+
+**Researched:** 2026-03-18
+**Domain:** Python Proxy Pool Management / Playwright Proxy Integration
+**Confidence:** HIGH
+
+## Summary
+
+本研究针对代理池基础设施的实现方案,重点解决多代理配置、自动轮换、健康检查和失效回退四个核心需求。基于现有 `kb_workflow/crawler/config.py` 的单代理实现,推荐采用 **ProxyPool 类 + 被动健康检测 + 冷却恢复** 的架构模式。
+
+**Primary recommendation:** 新建 `kb_workflow/crawler/proxy_pool.py` 模块,实现 ProxyPool 类,使用 itertools.cycle 进行顺序轮换,通过惰性检查实现代理冷却恢复,与现有 CrawlerConfig 无缝集成。
+
+
+## User Constraints (from CONTEXT.md)
+
+### Implementation Decisions (Locked)
+
+#### 代理池配置方式
+- **配置来源**: YAML 文件(`~/.kb_proxies.yaml`)
+- **配置格式**: 简单 URL 列表,认证信息嵌入 URL
+ ```yaml
+ proxies:
+ - "http://user:pass@proxy1.example.com:8080"
+ - "http://proxy2.example.com:3128"
+ - "socks5://user:pass@proxy3.example.com:1080"
+ ```
+- **向后兼容**: 如果未配置代理池文件,自动回退到现有的 `HTTP_PROXY` 环境变量(单代理模式)
+- **支持的协议**: HTTP、HTTPS、SOCKS5
+
+#### 轮换策略
+- **策略**: 顺序轮换(Round-Robin)
+- **时机**: 每次请求自动轮换到下一个代理
+- **实现**: 维护一个索引指针,每次请求后递增并循环
+
+#### 健康检查机制
+- **检测方式**: 被动检测(请求失败时标记)
+- **失效判断**: 连续 3 次请求失败后标记为失效
+- **失败类型**: 网络超时、连接失败、代理返回错误
+
+#### 失效代理处理
+- **策略**: 暂时移除 + 冷却恢复
+- **冷却时间**: 5 分钟后自动恢复到轮换池
+- **全失效处理**: 所有代理都失效时,回退到第一个代理继续尝试请求
+
+### Claude's Discretion
+- 冷却时间的具体实现方式(定时器 vs 惰性检查)
+- 代理统计信息的记录格式(可选功能)
+- 日志输出的详细程度
+- 失效代理的具体判断条件(HTTP 状态码范围)
+
+### Deferred Ideas (OUT OF SCOPE)
+- **API 获取代理** — 从代理服务商 API 自动获取代理
+- **加权轮换** — 根据代理质量/速度加权
+- **代理统计面板** — 展示每个代理的成功率、响应时间
+- **配置热加载** — 运行时检测配置文件变化并重新加载
+
+
+
+## Phase Requirements
+
+| ID | Description | Research Support |
+|----|-------------|-----------------|
+| PROXY-01 | 用户可以配置代理池 — 支持从文件或环境变量加载多个代理地址 | YAML 配置 + Pydantic BaseModel 解析 + 向后兼容环境变量 |
+| PROXY-02 | 系统自动轮换代理 — 每次请求自动选择下一个可用代理 | itertools.cycle + 索引指针实现 Round-Robin |
+| PROXY-03 | 代理健康检查 — 检测代理可用性,自动移除失效代理 | 被动检测(失败计数)+ 连续3次失败标记失效 |
+| PROXY-04 | 代理失败回退 — 当前代理失败时自动切换到下一个代理 | 失效代理跳过 + 冷却恢复 + 全失效回退策略 |
+
+
+## Standard Stack
+
+### Core
+| Library | Version | Purpose | Why Standard |
+|---------|---------|---------|--------------|
+| Pydantic | 2.11+ | ProxyConfig 数据模型 | 项目已使用;类型安全;支持 SecretStr 敏感字段 |
+| pydantic-settings | 2.8+ | 配置管理 | 项目已使用;支持 YAML/环境变量加载 |
+| PyYAML | 6.0+ | YAML 配置解析 | Python 标准库;轻量级 |
+| itertools (stdlib) | - | cycle() 实现轮换 | 零依赖;高效无限迭代器 |
+
+### Supporting
+| Library | Version | Purpose | When to Use |
+|---------|---------|---------|-------------|
+| tenacity | 8.5+ | 重试机制(现有) | 代理失败时的重试策略 |
+| loguru | 0.7+ | 日志记录 | 代理状态变化日志 |
+
+### Alternatives Considered
+| Instead of | Could Use | Tradeoff |
+|------------|-----------|----------|
+| 自定义 ProxyPool | rotating-proxy 库 | 代码质量差、维护不活跃、不支持自定义配置源 |
+| 自定义 ProxyPool | scrapy-rotating-proxies | 与 Scrapy 绑定、不适用于 Playwright |
+| 被动检测 | 主动健康检查 | 主动检测增加延迟和复杂度;被动检测足够满足需求 |
+| 惰性冷却检查 | 定时器后台任务 | 定时器需要线程/异步;惰性检查更简单、无并发问题 |
+
+**Installation:**
+```bash
+# 项目已有依赖,无需新增
+# Pydantic, pydantic-settings, PyYAML 均已安装
+```
+
+## Architecture Patterns
+
+### Recommended Project Structure
+```
+kb_workflow/crawler/
+├── config.py # 现有:CrawlerConfig, ProxyConfig(扩展)
+├── proxy_pool.py # 新增:ProxyPool, ProxyEntry, ProxyPoolConfig
+├── zhihu_crawler.py # 修改:使用 ProxyPool
+└── models.py # 现有:CrawlResult 等
+```
+
+### Pattern 1: ProxyPool 类设计
+
+**What:** 代理池核心类,管理多个代理的生命周期
+
+**When to use:** 每个爬虫实例一个 ProxyPool,处理该爬虫的所有代理相关逻辑
+
+**Example:**
+```python
+# Source: 基于现有代码模式和 Infatica 最佳实践
+from dataclasses import dataclass, field
+from datetime import datetime, timedelta
+from typing import Optional, Iterator
+from itertools import cycle
+from pathlib import Path
+import yaml
+
+from pydantic import BaseModel
+import logging
+
+logger = logging.getLogger(__name__)
+
+
+class ProxyEntry(BaseModel):
+ """单个代理的配置和状态"""
+ url: str # 完整 URL,包含认证信息
+ fail_count: int = 0 # 连续失败次数
+ last_fail_time: Optional[datetime] = None # 最后失败时间
+ is_available: bool = True # 当前是否可用
+
+ def record_success(self):
+ """记录请求成功"""
+ self.fail_count = 0
+ self.is_available = True
+
+ def record_failure(self):
+ """记录请求失败"""
+ self.fail_count += 1
+ self.last_fail_time = datetime.now()
+ if self.fail_count >= 3:
+ self.is_available = False
+ logger.warning(f"Proxy marked as unavailable: {self.url[:30]}...")
+
+ def check_recovery(self, cooldown_seconds: int = 300) -> bool:
+ """检查是否可以从冷却中恢复(惰性检查)"""
+ if self.is_available:
+ return True
+ if self.last_fail_time is None:
+ return True
+ elapsed = (datetime.now() - self.last_fail_time).total_seconds()
+ if elapsed >= cooldown_seconds:
+ self.is_available = True
+ self.fail_count = 0
+ logger.info(f"Proxy recovered after {elapsed:.0f}s cooldown")
+ return True
+ return False
+
+
+class ProxyPoolConfig(BaseModel):
+ """代理池配置"""
+ proxies: list[str] = [] # 代理 URL 列表
+ cooldown_seconds: int = 300 # 冷却时间(秒)
+ max_fail_count: int = 3 # 最大连续失败次数
+
+
+class ProxyPool:
+ """代理池管理器
+
+ 功能:
+ - 从 YAML 文件或环境变量加载代理列表
+ - Round-Robin 轮换
+ - 被动健康检测
+ - 冷却恢复
+ """
+
+ def __init__(self, config: ProxyPoolConfig):
+ self.config = config
+ self._entries: list[ProxyEntry] = [
+ ProxyEntry(url=url) for url in config.proxies
+ ]
+ self._current_index = 0
+ self._cycle: Optional[Iterator] = None
+ if self._entries:
+ self._cycle = cycle(self._entries)
+
+ @classmethod
+ def from_yaml(cls, path: Path) -> "ProxyPool":
+ """从 YAML 文件加载代理池"""
+ if not path.exists():
+ logger.debug(f"Proxy config file not found: {path}")
+ return cls(ProxyPoolConfig())
+
+ with open(path) as f:
+ data = yaml.safe_load(f) or {}
+
+ proxies = data.get("proxies", [])
+ return cls(ProxyPoolConfig(proxies=proxies))
+
+ @classmethod
+ def from_env_fallback(cls) -> "ProxyPool":
+ """从环境变量加载单代理(向后兼容)"""
+ import os
+ proxy_url = os.environ.get("HTTPS_PROXY") or os.environ.get("HTTP_PROXY")
+ if proxy_url:
+ return cls(ProxyPoolConfig(proxies=[proxy_url]))
+ return cls(ProxyPoolConfig())
+
+ def get_next_proxy(self) -> Optional[ProxyEntry]:
+ """获取下一个可用代理
+
+ 实现逻辑:
+ 1. 惰性检查当前代理是否可恢复
+ 2. 跳过不可用的代理
+ 3. 所有代理都失效时,回退到第一个代理
+ """
+ if not self._entries:
+ return None
+
+ if len(self._entries) == 1:
+ # 单代理模式:总是返回该代理
+ return self._entries[0]
+
+ # 尝试找到可用代理
+ checked = set()
+ while len(checked) < len(self._entries):
+ entry = self._entries[self._current_index]
+ self._current_index = (self._current_index + 1) % len(self._entries)
+ checked.add(self._current_index)
+
+ # 惰性检查恢复
+ if entry.check_recovery(self.config.cooldown_seconds):
+ return entry
+
+ # 所有代理都失效,回退到第一个代理强制使用
+ logger.warning("All proxies unavailable, falling back to first proxy")
+ return self._entries[0]
+
+ def has_proxies(self) -> bool:
+ """检查是否有配置的代理"""
+ return len(self._entries) > 0
+
+ def get_available_count(self) -> int:
+ """获取当前可用代理数量"""
+ return sum(
+ 1 for e in self._entries
+ if e.check_recovery(self.config.cooldown_seconds)
+ )
+```
+
+### Pattern 2: CrawlerConfig 集成
+
+**What:** 扩展现有 CrawlerConfig 支持 ProxyPool
+
+**When to use:** 爬虫初始化时加载代理池配置
+
+**Example:**
+```python
+# Source: 基于现有 config.py 扩展
+from pathlib import Path
+
+def get_crawler_config_with_pool() -> tuple["CrawlerConfig", ProxyPool]:
+ """获取爬虫配置和代理池
+
+ 优先级:
+ 1. ~/.kb_proxies.yaml(代理池)
+ 2. HTTP_PROXY/HTTPS_PROXY(单代理,向后兼容)
+ """
+ proxy_file = Path.home() / ".kb_proxies.yaml"
+ proxy_pool = ProxyPool.from_yaml(proxy_file)
+
+ if not proxy_pool.has_proxies():
+ # 回退到环境变量
+ proxy_pool = ProxyPool.from_env_fallback()
+
+ # 原有配置逻辑
+ config = CrawlerConfig.from_env()
+
+ return config, proxy_pool
+```
+
+### Pattern 3: ZhihuCrawler 集成
+
+**What:** 修改 ZhihuCrawler 使用 ProxyPool
+
+**When to use:** 每次启动浏览器时从代理池获取代理
+
+**Example:**
+```python
+# Source: 基于现有 zhihu_crawler.py 修改
+class ZhihuCrawler:
+ def __init__(
+ self,
+ headless: bool = True,
+ timeout: int = 30,
+ config: Optional[CrawlerConfig] = None,
+ proxy_pool: Optional[ProxyPool] = None
+ ):
+ self.headless = headless
+ self.timeout = timeout
+ self.config = config or get_crawler_config()
+ self.proxy_pool = proxy_pool # 新增
+ # ...
+
+ def _start_browser_with_proxy(self, cookie: str) -> None:
+ """启动浏览器,从代理池获取代理"""
+ self.config.validate_proxy()
+
+ self._playwright = sync_playwright().start()
+ self._browser = self._playwright.chromium.launch(headless=self.headless)
+
+ context_options = {
+ 'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...'
+ }
+
+ # 从代理池获取代理
+ if self.proxy_pool and self.proxy_pool.has_proxies():
+ proxy_entry = self.proxy_pool.get_next_proxy()
+ if proxy_entry:
+ proxy_config = self._parse_proxy_url(proxy_entry.url)
+ context_options["proxy"] = proxy_config
+ self._current_proxy = proxy_entry # 保存当前代理引用
+ elif self.config.proxy:
+ # 向后兼容:使用单代理配置
+ context_options["proxy"] = self.config.proxy.to_playwright_format()
+
+ context_options["service_workers"] = "block"
+ self._context = self._browser.new_context(**context_options)
+ # ...
+
+ def _on_request_success(self):
+ """请求成功时通知代理池"""
+ if hasattr(self, '_current_proxy') and self._current_proxy:
+ self._current_proxy.record_success()
+
+ def _on_request_failure(self):
+ """请求失败时通知代理池"""
+ if hasattr(self, '_current_proxy') and self._current_proxy:
+ self._current_proxy.record_failure()
+```
+
+### Anti-Patterns to Avoid
+
+- **每次请求创建新浏览器** — Playwright 浏览器启动成本高,应在同一代理上处理多个请求后再切换
+- **主动健康检查** — 增加延迟;被动检测足够
+- **硬编码冷却时间** — 应通过配置文件可配置
+- **忽略 SOCKS5 代理** — 需要额外依赖 `requests[socks]`,Playwright 原生支持
+
+## Don't Hand-Roll
+
+| Problem | Don't Build | Use Instead | Why |
+|---------|-------------|-------------|-----|
+| 代理轮换逻辑 | 手写 while 循环 | `itertools.cycle()` | 边界处理复杂、容易死循环 |
+| 配置解析 | 手写正则提取 URL | `urllib.parse.urlparse()` | URL 格式多变、边界情况多 |
+| 代理认证提取 | 字符串 split | Pydantic BaseModel | 类型安全、自动验证 |
+| 冷却时间计算 | 手写时间差 | `datetime.timedelta` | 时区、精度问题 |
+
+**Key insight:** 代理池看似简单,但边界情况极多(URL 解析、认证、协议差异、失败重试)。使用标准库和 Pydantic 可以避免大部分陷阱。
+
+## Common Pitfalls
+
+### Pitfall 1: 代理配置不完整导致真实 IP 泄漏
+
+**What goes wrong:** 只配置了 HTTP 代理但未配置 HTTPS 代理,或 Playwright proxy 配置不完整,导致部分请求绕过代理暴露真实 IP。
+
+**Why it happens:** 开发者通常只关注主要请求的代理配置,忽略了 Playwright 的 `proxy` 参数需要正确格式。
+
+**How to avoid:**
+```python
+# 正确的 Playwright 代理配置
+context_options = {
+ "proxy": {
+ "server": "http://proxy.example.com:8080",
+ "username": "user", # 可选
+ "password": "pass", # 可选
+ }
+}
+```
+
+**Warning signs:**
+- 使用代理后仍然收到 403 错误
+- 目标平台显示真实地理位置
+- IP 检测 API 返回真实 IP 而非代理 IP
+
+### Pitfall 2: 固定间隔轮换被识别为机器人
+
+**What goes wrong:** 每次请求后立即切换代理,顺序固定(A→B→C→A),被反爬系统识别为自动化行为。
+
+**Why it happens:** Round-Robin 是最简单的实现,但对于个人知识库场景(低频爬取),顺序轮换配合随机请求延迟已经足够。
+
+**How to avoid:** 本项目采用 **会话级轮换**(每个浏览器会话使用一个代理),而非请求级轮换。结合 Phase 11 的随机延迟(1-5秒),风险可控。
+
+**Warning signs:**
+- 新代理 IP 很快被封
+- 频繁收到 CAPTCHA 挑战
+
+### Pitfall 3: 代理池全失效时无限循环
+
+**What goes wrong:** 所有代理都被标记为失效后,`get_next_proxy()` 返回 None 或进入死循环。
+
+**Why it happens:** 只考虑了正常情况,没有处理边界条件。
+
+**How to avoid:**
+```python
+def get_next_proxy(self) -> Optional[ProxyEntry]:
+ # ... 轮换逻辑 ...
+
+ # 所有代理都失效时,回退到第一个代理
+ logger.warning("All proxies unavailable, falling back to first proxy")
+ return self._entries[0] # 强制使用第一个
+```
+
+### Pitfall 4: 代理 URL 解析错误
+
+**What goes wrong:** SOCKS5 代理格式为 `socks5://user:pass@host:port`,但解析时只处理了 HTTP 格式。
+
+**Why it happens:** 不同协议的 URL 格式略有差异,手动解析容易遗漏。
+
+**How to avoid:**
+```python
+from urllib.parse import urlparse
+
+def parse_proxy_url(url: str) -> dict:
+ """解析代理 URL 为 Playwright 格式"""
+ parsed = urlparse(url)
+ server = f"{parsed.scheme}://{parsed.hostname}"
+ if parsed.port:
+ server += f":{parsed.port}"
+
+ config = {"server": server}
+ if parsed.username:
+ config["username"] = parsed.username
+ if parsed.password:
+ config["password"] = parsed.password
+ return config
+```
+
+## Code Examples
+
+### 配置文件示例 (~/.kb_proxies.yaml)
+
+```yaml
+# KB Skills 代理池配置
+# 支持格式:http://[user:pass@]host:port, socks5://[user:pass@]host:port
+
+proxies:
+ # 本地代理(Clash/V2Ray)
+ - "http://127.0.0.1:7890"
+
+ # 带认证的 HTTP 代理
+ - "http://user:password@proxy.example.com:8080"
+
+ # SOCKS5 代理
+ - "socks5://127.0.0.1:1080"
+
+# 可选:冷却时间(秒),默认 300
+cooldown_seconds: 300
+
+# 可选:最大连续失败次数,默认 3
+max_fail_count: 3
+```
+
+### 代理池初始化
+
+```python
+# Source: 推荐的初始化模式
+from pathlib import Path
+from kb_workflow.crawler.proxy_pool import ProxyPool
+
+def init_proxy_pool() -> ProxyPool:
+ """初始化代理池,优先从配置文件加载"""
+ proxy_file = Path.home() / ".kb_proxies.yaml"
+
+ # 优先级 1: YAML 配置文件
+ if proxy_file.exists():
+ pool = ProxyPool.from_yaml(proxy_file)
+ if pool.has_proxies():
+ return pool
+
+ # 优先级 2: 环境变量(向后兼容)
+ pool = ProxyPool.from_env_fallback()
+ return pool
+```
+
+### 爬虫使用代理池
+
+```python
+# Source: ZhihuCrawler 集成示例
+from kb_workflow.crawler.config import get_crawler_config
+from kb_workflow.crawler.proxy_pool import ProxyPool, init_proxy_pool
+
+# 初始化
+config = get_crawler_config()
+proxy_pool = init_proxy_pool()
+
+# 创建爬虫
+crawler = ZhihuCrawler(
+ headless=True,
+ timeout=30,
+ config=config,
+ proxy_pool=proxy_pool
+)
+
+# 爬取时代理自动轮换
+result = crawler.crawl_answer("https://www.zhihu.com/question/123/answer/456")
+```
+
+## State of the Art
+
+| Old Approach | Current Approach | When Changed | Impact |
+|--------------|------------------|--------------|--------|
+| 单代理硬编码 | 环境变量配置 | v1.2 | 更灵活,支持不同环境 |
+| 环境变量单代理 | YAML 配置文件代理池 | v1.3 (Phase 10) | 支持多代理、轮换、健康检查 |
+| 主动健康检查 | 被动检测 | v1.3 (Phase 10) | 减少延迟,简化实现 |
+| 立即移除失效代理 | 冷却恢复 | v1.3 (Phase 10) | 代理可恢复使用,提高利用率 |
+
+**Deprecated/outdated:**
+- `rotating-proxy` 库:2020年后无更新,代码质量差
+- `scrapy-rotating-proxies`:与 Scrapy 绑定,不适用于 Playwright
+
+## Open Questions
+
+1. **冷却检查时机:惰性检查 vs 定时器?**
+ - What we know: 惰性检查在 `get_next_proxy()` 时执行,无需额外线程/异步
+ - What's unclear: 高并发场景下惰性检查的性能影响
+ - Recommendation: 本项目为单线程顺序执行,惰性检查足够;如未来需要并发,可迁移到定时器
+
+2. **代理统计信息是否需要持久化?**
+ - What we know: 当前设计只在内存中维护状态
+ - What's unclear: 是否需要将代理成功率持久化到文件
+ - Recommendation: v1.3 暂不持久化;如后续需要统计面板,再添加
+
+## Validation Architecture
+
+### Test Framework
+| Property | Value |
+|----------|-------|
+| Framework | pytest 8.3+ |
+| Config file | pytest.ini (pythonpath = ., testpaths = tests) |
+| Quick run command | `pytest tests/test_crawler/test_proxy_pool.py -x` |
+| Full suite command | `pytest tests/test_crawler/ -v` |
+
+### Phase Requirements → Test Map
+| Req ID | Behavior | Test Type | Automated Command | File Exists? |
+|--------|----------|-----------|-------------------|-------------|
+| PROXY-01 | 从 YAML 文件加载代理池 | unit | `pytest tests/test_crawler/test_proxy_pool.py::test_load_from_yaml -x` | ❌ Wave 0 |
+| PROXY-01 | 从环境变量加载代理(向后兼容) | unit | `pytest tests/test_crawler/test_proxy_pool.py::test_load_from_env -x` | ❌ Wave 0 |
+| PROXY-02 | Round-Robin 轮换 | unit | `pytest tests/test_crawler/test_proxy_pool.py::test_round_robin -x` | ❌ Wave 0 |
+| PROXY-03 | 连续3次失败标记失效 | unit | `pytest tests/test_crawler/test_proxy_pool.py::test_fail_threshold -x` | ❌ Wave 0 |
+| PROXY-03 | 冷却恢复 | unit | `pytest tests/test_crawler/test_proxy_pool.py::test_cooldown_recovery -x` | ❌ Wave 0 |
+| PROXY-04 | 全失效回退 | unit | `pytest tests/test_crawler/test_proxy_pool.py::test_all_unavailable_fallback -x` | ❌ Wave 0 |
+| PROXY-04 | 代理切换后继续请求 | integration | `pytest tests/test_crawler/test_proxy_pool.py::test_proxy_switch -x` | ❌ Wave 0 |
+
+### Sampling Rate
+- **Per task commit:** `pytest tests/test_crawler/test_proxy_pool.py -x`
+- **Per wave merge:** `pytest tests/test_crawler/ -v`
+- **Phase gate:** Full suite green before `/gsd:verify-work`
+
+### Wave 0 Gaps
+- [ ] `tests/test_crawler/test_proxy_pool.py` — 代理池核心逻辑测试
+- [ ] `tests/test_crawler/conftest.py` — 添加 proxy_pool fixture(已存在,可能需要扩展)
+- [ ] 无需框架安装 — pytest 已配置
+
+## Sources
+
+### Primary (HIGH confidence)
+- [Infatica: Master Proxy Rotation with Python's Requests Library](https://infatica.io/blog/python-proxy-requests/) — Round-Robin 实现、代理轮换最佳实践
+- [Playwright Python Documentation - Network](https://playwright.dev/python/docs/network) — Playwright 代理配置官方文档
+- [tenacity Documentation](https://tenacity.readthedocs.io/) — Python 重试库官方文档(现有依赖)
+
+### Secondary (MEDIUM confidence)
+- [Oxylabs: How to Rotate Proxies in Python](https://oxylabs.io/blog/rotate-proxies-python) — 代理轮换策略概述
+- [Stack Overflow: Round Robin proxy rotation](https://stackoverflow.com/questions/74110824/how-to-make-different-session-proxy-with-each-request) — 实现代码示例
+
+### Tertiary (LOW confidence)
+- [DEV.to: Proxy Rotation for Web Scraping in 2026](https://dev.to/agenthustler/proxy-rotation-for-web-scraping-in-2026-the-complete-guide-with-code-23d) — 通用指南(需验证)
+
+### Code Analysis (HIGH confidence)
+- `kb_workflow/crawler/config.py` — 现有代理配置实现
+- `kb_workflow/crawler/zhihu_crawler.py` — 现有爬虫实现
+- `.planning/research/PITFALLS.md` — 反爬虫陷阱研究
+- `.planning/research/STACK.md` — 技术栈研究
+
+## Metadata
+
+**Confidence breakdown:**
+- Standard stack: HIGH — 基于现有项目依赖和官方文档
+- Architecture: HIGH — 基于现有代码模式和最佳实践
+- Pitfalls: HIGH — 基于项目 PITFALLS.md 和社区经验
+
+**Research date:** 2026-03-18
+**Valid until:** 30 days (稳定技术栈)