docs: update research for v1.3 anti-crawler optimization
PR Test / lint (pull_request) Successful in 2s
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>
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
---
|
||||
phase: 10
|
||||
slug: proxy-pool
|
||||
status: draft
|
||||
nyquist_compliant: false
|
||||
wave_0_complete: false
|
||||
created: 2026-03-18
|
||||
---
|
||||
|
||||
# Phase 10 — Validation Strategy
|
||||
|
||||
> Per-phase validation contract for feedback sampling during execution.
|
||||
|
||||
---
|
||||
|
||||
## Test Infrastructure
|
||||
|
||||
| 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` |
|
||||
| **Estimated runtime** | ~5 seconds |
|
||||
|
||||
---
|
||||
|
||||
## Sampling Rate
|
||||
|
||||
- **After every task commit:** Run `pytest tests/test_crawler/test_proxy_pool.py -x`
|
||||
- **After every plan wave:** Run `pytest tests/test_crawler/ -v`
|
||||
- **Before `/gsd:verify-work`:** Full suite must be green
|
||||
- **Max feedback latency:** 5 seconds
|
||||
|
||||
---
|
||||
|
||||
## Per-Task Verification Map
|
||||
|
||||
| Task ID | Plan | Wave | Requirement | Test Type | Automated Command | File Exists | Status |
|
||||
|---------|------|------|-------------|-----------|-------------------|-------------|--------|
|
||||
| 10-01-01 | 01 | 1 | PROXY-01 | unit | `pytest tests/test_crawler/test_proxy_pool.py::test_load_from_yaml -x` | ❌ W0 | ⬜ pending |
|
||||
| 10-01-02 | 01 | 1 | PROXY-01 | unit | `pytest tests/test_crawler/test_proxy_pool.py::test_load_from_env -x` | ❌ W0 | ⬜ pending |
|
||||
| 10-01-03 | 01 | 1 | PROXY-02 | unit | `pytest tests/test_crawler/test_proxy_pool.py::test_round_robin -x` | ❌ W0 | ⬜ pending |
|
||||
| 10-02-01 | 02 | 1 | PROXY-03 | unit | `pytest tests/test_crawler/test_proxy_pool.py::test_fail_threshold -x` | ❌ W0 | ⬜ pending |
|
||||
| 10-02-02 | 02 | 1 | PROXY-03 | unit | `pytest tests/test_crawler/test_proxy_pool.py::test_cooldown_recovery -x` | ❌ W0 | ⬜ pending |
|
||||
| 10-02-03 | 02 | 1 | PROXY-04 | unit | `pytest tests/test_crawler/test_proxy_pool.py::test_all_unavailable_fallback -x` | ❌ W0 | ⬜ pending |
|
||||
| 10-02-04 | 02 | 1 | PROXY-04 | integration | `pytest tests/test_crawler/test_proxy_pool.py::test_proxy_switch -x` | ❌ W0 | ⬜ pending |
|
||||
|
||||
*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*
|
||||
|
||||
---
|
||||
|
||||
## Wave 0 Requirements
|
||||
|
||||
- [ ] `tests/test_crawler/test_proxy_pool.py` — stubs for PROXY-01~04
|
||||
- [ ] `tests/test_crawler/conftest.py` — add proxy_pool fixture (extend existing)
|
||||
- [ ] No framework install needed — pytest already configured
|
||||
|
||||
---
|
||||
|
||||
## Manual-Only Verifications
|
||||
|
||||
| Behavior | Requirement | Why Manual | Test Instructions |
|
||||
|----------|-------------|------------|-------------------|
|
||||
| Real proxy connection | PROXY-01~04 | Requires external proxy service | Configure ~/.kb_proxies.yaml with real proxies, run crawler |
|
||||
|
||||
*All phase behaviors have automated verification for core logic. Manual verification only for integration with external proxy services.*
|
||||
|
||||
---
|
||||
|
||||
## Validation Sign-Off
|
||||
|
||||
- [ ] All tasks have `<automated>` verify or Wave 0 dependencies
|
||||
- [ ] Sampling continuity: no 3 consecutive tasks without automated verify
|
||||
- [ ] Wave 0 covers all MISSING references
|
||||
- [ ] No watch-mode flags
|
||||
- [ ] Feedback latency < 5s
|
||||
- [ ] `nyquist_compliant: true` set in frontmatter
|
||||
|
||||
**Approval:** pending
|
||||
File diff suppressed because it is too large
Load Diff
+232
-11
@@ -1,10 +1,206 @@
|
||||
# Feature Research
|
||||
|
||||
**Domain:** Skill-based Workflow Orchestration (Content Processing Pipelines)
|
||||
**Researched:** 2026-03-13
|
||||
**Confidence:** HIGH
|
||||
**Researched:** 2026-03-13 (Updated: 2026-03-18 for v1.3 Anti-Crawler)
|
||||
**Confidence:** HIGH (v1.0-1.2) / MEDIUM (v1.3 Anti-Crawler - 基于社区实践)
|
||||
|
||||
## Feature Landscape
|
||||
---
|
||||
|
||||
## v1.3 Milestone: Anti-Crawler Optimization Features
|
||||
|
||||
**Focus:** 增强爬虫反检测能力,降低被封风险,提升爬取稳定性
|
||||
|
||||
---
|
||||
|
||||
### Table Stakes (Users Expect These)
|
||||
|
||||
反爬虫优化中用户默认应该有的功能,缺失会让产品感觉不完整。
|
||||
|
||||
| Feature | Why Expected | Complexity | Notes |
|
||||
|---------|--------------|------------|-------|
|
||||
| **代理 IP 轮换** | 防止单 IP 被封,是反爬虫基础 | MEDIUM | 当前已有基础代理支持,需扩展为池化管理 |
|
||||
| **请求延迟** | 避免触发频率限制 | LOW | 当前已实现随机延迟 (1-3s),可优化范围 |
|
||||
| **自动重试** | 网络波动时保证稳定性 | LOW | 当前已用 tenacity 实现指数退避重试 |
|
||||
| **错误码识别** | 根据响应状态调整行为 | MEDIUM | 需区分临时错误 vs 永久错误 vs 封禁 |
|
||||
|
||||
### Differentiators (Competitive Advantage)
|
||||
|
||||
能让 kb-skills 脱颖而出的功能。不是必须的,但有价值。
|
||||
|
||||
| Feature | Value Proposition | Complexity | Notes |
|
||||
|---------|-------------------|------------|-------|
|
||||
| **智能代理轮换** | 根据代理健康度、响应时间动态选择 | HIGH | 比简单轮询更有效,降低失败率 |
|
||||
| **请求行为伪装** | 模拟人类浏览模式 | MEDIUM | 随机化 User-Agent、请求顺序、停留时间 |
|
||||
| **验证码检测与告警** | 遇到验证码时暂停并通知,而非静默失败 | MEDIUM | 个人使用场景:检测后暂停等待手动处理 |
|
||||
| **平台特定适配** | 针对知乎/B站的不同反爬策略 | MEDIUM | 知乎 x-zse-96 签名 vs B站 WBI 签名 |
|
||||
| **断点续传增强** | 记录失败原因,智能恢复 | MEDIUM | 区分"需要换 IP" vs "需要换策略" |
|
||||
|
||||
### Anti-Features (Commonly Requested, Often Problematic)
|
||||
|
||||
看似好但会带来问题的功能。
|
||||
|
||||
| Feature | Why Requested | Why Problematic | Alternative |
|
||||
|---------|---------------|-----------------|-------------|
|
||||
| **自动验证码破解** | 无人值守运行 | 1) 需要付费打码服务 2) 违反网站 ToS 3) 增加法律风险 | 检测后暂停,用户手动处理 |
|
||||
| **高并发爬取** | 提高效率 | 1) 更容易触发封禁 2) 增加被检测风险 3) 违背"个人知识库"定位 | 顺序执行 + 合理延迟 |
|
||||
| **复杂指纹伪装** | 绕过高级检测 | 1) 实现复杂 2) 维护成本高 3) 对当前目标网站不必要 | 基础 User-Agent 轮换足够 |
|
||||
| **SOCKS5 代理池** | 更高匿名性 | 1) 住宅代理更有效 2) 当前场景不需要 3) 增加配置复杂度 | HTTP/HTTPS 代理足够 |
|
||||
|
||||
---
|
||||
|
||||
## Platform-Specific Anti-Crawler Measures
|
||||
|
||||
### 知乎 (Zhihu) 反爬策略
|
||||
|
||||
| 检测类型 | 描述 | 应对策略 |
|
||||
|---------|------|---------|
|
||||
| **x-zse-96 签名** | API 请求需要动态签名 | Playwright 自动处理 (当前已实现) |
|
||||
| **Cookie 验证** | 需要登录态 | 二维码扫码登录 (当前已实现) |
|
||||
| **请求频率限制** | 单 IP 高频请求触发限制 | 代理轮换 + 随机延迟 |
|
||||
| **验证码触发** | 异常行为弹出验证码 | 检测 + 暂停 + 告警 |
|
||||
|
||||
**知乎特征响应:**
|
||||
- 401: Cookie 过期
|
||||
- 403: 被限制访问
|
||||
- 验证码页面: HTML 包含 "验证" 或特定元素
|
||||
|
||||
### B站 (Bilibili) 反爬策略
|
||||
|
||||
| 检测类型 | 描述 | 应对策略 |
|
||||
|---------|------|---------|
|
||||
| **WBI 签名** | Web API 需要 w_rid + wts 参数 | 实现签名算法或使用 Playwright |
|
||||
| **Referer 校验** | 需要 `https://www.bilibili.com/` | 设置正确 Referer 头 |
|
||||
| **请求频率限制** | 建议 <60 次/分钟/IP | 代理轮换 + 限流 |
|
||||
| **352 风控** | 异常请求拦截机制 | 监控错误码,调整行为 |
|
||||
|
||||
**B站特征响应:**
|
||||
- -799: 请求过于频繁
|
||||
- -400: 请求错误
|
||||
- -352: 风控拦截
|
||||
|
||||
---
|
||||
|
||||
## v1.3 Feature Dependencies
|
||||
|
||||
```
|
||||
代理 IP 轮换
|
||||
└──requires──> 代理池配置 (PROXY_POOL 环境变量或配置文件)
|
||||
└──enhances──> 错误恢复机制 (根据错误类型决定是否换 IP)
|
||||
|
||||
验证码检测
|
||||
└──requires──> 响应内容分析 (HTML/JSON 解析)
|
||||
└──triggers──> 用户告警系统 (当前可用日志/控制台输出)
|
||||
|
||||
平台特定适配
|
||||
└──requires──> 平台识别逻辑 (URL 解析)
|
||||
└──requires──> 平台签名算法 (知乎 x-zse-96 / B站 WBI)
|
||||
|
||||
错误恢复机制
|
||||
└──requires──> 错误分类 (临时/永久/封禁)
|
||||
└──requires──> 重试策略配置 (指数退避参数)
|
||||
└──conflicts──> 快速失败模式 (某些场景需要立即报错)
|
||||
|
||||
请求行为伪装
|
||||
└──enhances──> 代理 IP 轮换 (完整伪装链)
|
||||
└──enhances──> 验证码规避 (减少触发概率)
|
||||
```
|
||||
|
||||
### Dependency Notes
|
||||
|
||||
- **代理 IP 轮换 requires 代理池配置:** 需要支持多种配置方式 (环境变量、配置文件、API 获取)
|
||||
- **验证码检测 requires 响应内容分析:** 需要解析 HTML/JSON 识别验证码页面特征
|
||||
- **平台特定适配 requires 平台签名算法:** 知乎 x-zse-96 已通过 Playwright 自动处理;B站 WBI 需要实现签名算法
|
||||
- **错误恢复机制 conflicts 快速失败模式:** 可通过配置选择模式,默认使用重试
|
||||
|
||||
---
|
||||
|
||||
## v1.3 MVP Definition
|
||||
|
||||
### Launch With (v1.3 MVP)
|
||||
|
||||
最低可行产品 - 验证反爬虫优化核心价值。
|
||||
|
||||
- [ ] **代理池管理** — 支持配置多个代理,轮换使用 — 核心反封能力
|
||||
- [ ] **随机延迟优化** — 扩展延迟范围 (1-10s),增加随机性 — 低成本高效
|
||||
- [ ] **错误分类与智能重试** — 区分临时错误/永久错误/封禁 — 避免无效重试
|
||||
- [ ] **验证码检测** — 检测验证码页面并暂停 — 避免静默失败
|
||||
|
||||
### Add After Validation (v1.x)
|
||||
|
||||
核心功能验证后添加的增强功能。
|
||||
|
||||
- [ ] **代理健康检查** — 检测代理可用性,自动剔除失效代理 — 当发现代理失败率高时
|
||||
- [ ] **B站 WBI 签名** — 支持 B站 API 签名 — 当需要直接调用 B站 API 时
|
||||
- [ ] **请求行为伪装增强** — User-Agent 轮换、请求头随机化 — 当基础策略不够用时
|
||||
|
||||
### Future Consideration (v2+)
|
||||
|
||||
推迟到产品稳定后的功能。
|
||||
|
||||
- [ ] **智能代理选择** — 根据历史成功率加权选择 — 需要足够的运行数据
|
||||
- [ ] **自动验证码告警** — 桌面通知/邮件通知 — 当需要无人值守时
|
||||
- [ ] **分布式代理池** — 支持从 API 获取代理列表 — 需要代理服务订阅
|
||||
|
||||
---
|
||||
|
||||
## v1.3 Feature Prioritization Matrix
|
||||
|
||||
| Feature | User Value | Implementation Cost | Priority |
|
||||
|---------|------------|---------------------|----------|
|
||||
| 代理池管理 | HIGH | MEDIUM | P1 |
|
||||
| 随机延迟优化 | HIGH | LOW | P1 |
|
||||
| 错误分类与智能重试 | HIGH | MEDIUM | P1 |
|
||||
| 验证码检测 | MEDIUM | LOW | P1 |
|
||||
| 代理健康检查 | MEDIUM | MEDIUM | P2 |
|
||||
| User-Agent 轮换 | MEDIUM | LOW | P2 |
|
||||
| B站 WBI 签名 | LOW* | MEDIUM | P2 |
|
||||
| 智能代理选择 | LOW | HIGH | P3 |
|
||||
|
||||
*注:B站 WBI 签名优先级取决于是否需要直接调用 API(当前 Playwright 方案可能已足够)
|
||||
|
||||
**Priority key:**
|
||||
- P1: Must have for v1.3
|
||||
- P2: Should have, add when possible
|
||||
- P3: Nice to have, future consideration
|
||||
|
||||
---
|
||||
|
||||
## Implementation Complexity Notes
|
||||
|
||||
### 代理池管理 (MEDIUM)
|
||||
- **配置方式**: 环境变量 `PROXY_POOL` (逗号分隔) 或配置文件
|
||||
- **轮换策略**: Round-robin (简单) vs 加权 (复杂)
|
||||
- **集成点**: 修改 `CrawlerConfig` 支持代理列表
|
||||
|
||||
### 验证码检测 (LOW-MEDIUM)
|
||||
- **知乎检测**: 检查响应中是否包含 "验证" 或验证码元素
|
||||
- **通用检测**: 检查 HTTP 状态码 + 响应内容特征
|
||||
- **处理方式**: 抛出特定异常,触发暂停和告警
|
||||
|
||||
### 错误分类 (MEDIUM)
|
||||
- **临时错误**: 网络超时、5xx 服务器错误 → 重试
|
||||
- **永久错误**: 404、权限不足 → 失败不重试
|
||||
- **封禁错误**: 403、验证码 → 换 IP/暂停
|
||||
|
||||
### 请求行为伪装 (LOW)
|
||||
- **User-Agent 池**: 预定义常见 UA 列表
|
||||
- **请求头随机化**: Accept-Language, Accept-Encoding 顺序随机
|
||||
- **会话行为**: 模拟页面停留、滚动 (Playwright 层面)
|
||||
|
||||
---
|
||||
|
||||
## v1.3 Competitor Feature Analysis
|
||||
|
||||
| Feature | Scrapy | Requests + tenacity | Our Approach |
|
||||
|---------|--------|---------------------|--------------|
|
||||
| 代理轮换 | 中间件支持 | 手动实现 | 配置驱动的池管理 |
|
||||
| 重试机制 | 内置 | tenacity 库 | tenacity (已集成) |
|
||||
| 限流 | AutoThrottle 扩展 | 手动 | 配置化延迟范围 |
|
||||
| 验证码 | 需插件 | 无 | 检测 + 暂停告警 |
|
||||
|
||||
---
|
||||
|
||||
## v1.0-1.2 Baseline Features (Preserved)
|
||||
|
||||
### Table Stakes (Users Expect These)
|
||||
|
||||
@@ -49,9 +245,10 @@ Features that seem good but create problems.
|
||||
| **Plugin/Extension System** | Third-party integrations | Security concerns; API stability requirements; documentation burden | Keep monolithic but modular skill architecture; internal extensions only |
|
||||
| **Workflow Visualization** | See pipeline graphically | Nice-to-have but not core value; generates maintenance burden | State file (JSON) is machine-readable; can generate viz later |
|
||||
| **Automatic Retry with Backoff** | Handle transient failures | Can mask underlying issues; retry logic is complex; may cause rate limiting | Explicit error reporting; manual retry with checkpoint resume |
|
||||
| **Complex Routing/Handoff Patterns** | Dynamic task delegation | Overkill for linear content processing; adds nondeterminism; harder to debug | Sequential orchestration with explicit steps |
|
||||
|
||||
## Feature Dependencies
|
||||
---
|
||||
|
||||
## v1.0-1.2 Feature Dependencies
|
||||
|
||||
```
|
||||
[URL Input]
|
||||
@@ -93,9 +290,11 @@ Features that seem good but create problems.
|
||||
- **Platform-Specific Skills require Link Parser:** Cannot extract metadata without knowing platform and content type
|
||||
- **Deep Analysis requires Text Content:** ASR/OCR must complete before AI analysis can process
|
||||
|
||||
## MVP Definition
|
||||
---
|
||||
|
||||
### Launch With (v1)
|
||||
## v1.0-1.2 MVP Definition
|
||||
|
||||
### Launch With (v1) - COMPLETED
|
||||
|
||||
Minimum viable product — what's needed to validate the concept.
|
||||
|
||||
@@ -126,7 +325,9 @@ Features to defer until product-market fit is established.
|
||||
- [ ] **Web UI for Monitoring** — Consider only if non-technical users need access
|
||||
- [ ] **API/Webhook Notifications** — If integration with external systems needed
|
||||
|
||||
## Feature Prioritization Matrix
|
||||
---
|
||||
|
||||
## v1.0-1.2 Feature Prioritization Matrix
|
||||
|
||||
| Feature | User Value | Implementation Cost | Priority |
|
||||
|---------|------------|---------------------|----------|
|
||||
@@ -150,6 +351,8 @@ Features to defer until product-market fit is established.
|
||||
- P2: Should have, add when possible (robustness)
|
||||
- P3: Nice to have, future consideration (convenience)
|
||||
|
||||
---
|
||||
|
||||
## Competitor Feature Analysis
|
||||
|
||||
| Feature | Apache Airflow | Dagster | Prefect | Our Approach |
|
||||
@@ -164,6 +367,8 @@ Features to defer until product-market fit is established.
|
||||
|
||||
**Key differentiation:** Our skill-based architecture with SKILL.md specifications makes the system more accessible to AI agents and easier to extend than traditional workflow engines. The focus on content processing (not general ETL) allows specialized optimizations.
|
||||
|
||||
---
|
||||
|
||||
## Industry Standard Features (2025-2026)
|
||||
|
||||
Based on research, modern data pipeline and workflow orchestration systems have these table stakes:
|
||||
@@ -185,11 +390,26 @@ Based on research, modern data pipeline and workflow orchestration systems have
|
||||
- Self-Service: SKILL.md specifications enable easy understanding
|
||||
- Multi-Format: Video + text + images supported
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
|
||||
- [Striim: 7 Must-Have Features of Modern Data Pipelines](https://www.striim.com/blog/what-is-a-data-pipeline-and-must-have-features-of-modern-data-pipelines/) - HIGH confidence
|
||||
- [Dagster: Data Pipeline Frameworks Key Features 2025](https://dagster.io/guides/data-pipeline-frameworks-key-features-10-tools-to-know-in-2025) - HIGH confidence
|
||||
- [Microsoft Azure: AI Agent Orchestration Patterns](https://learn.microsoft.com/en-us/azure/architecture/ai-ml/guide/ai-agent-design-patterns) - HIGH confidence
|
||||
### v1.3 Anti-Crawler Research (MEDIUM confidence)
|
||||
- [Bright Data - IP Rotation Best Practices](https://brightdata.com/faqs/ip-rotation/best-practices)
|
||||
- [ScrapFly - Bypass Anti-Bot Protection](https://scrapfly.io/blog/posts/how-to-bypass-anti-bot-protection-when-web-scraping)
|
||||
- [ScrapeHero - TLS Fingerprint Bypass 2026](https://www.scrapehero.com/tls-fingerprint-bypass-techniques/)
|
||||
- [CapMonster - Stop Getting CAPTCHA 2025](https://capmonster.cloud/en/blog/how-to-stop-getting-captcha-when-scraping-in-2025-with-real-solutions)
|
||||
- [OneUptime - Retry Logic with Exponential Backoff in Python](https://oneuptime.com/blog/post/2025-01-06-python-retry-exponential-backoff/view)
|
||||
- [AWS Prescriptive Guidance - Retry with Backoff Pattern](https://docs.aws.amazon.com/prescriptive-guidance/latest/cloud-design-patterns/retry-backoff.html)
|
||||
- [知乎专栏 - B站 WBI 签名分析](https://zhuanlan.zhihu.com/p/1961014749807513938)
|
||||
- [CSDN - B站视频爬取避坑指南 2024](https://blog.csdn.net/weixin_29051149/article/details/158076702)
|
||||
- [Zyte - Rotating Proxies in Python](https://www.zyte.com/blog/developers-guide-to-rotating-proxies-in-python/)
|
||||
- [Tenacity Library Documentation](https://github.com/jd/tenacity) - 当前项目已使用的重试库
|
||||
|
||||
### v1.0-1.2 Baseline Research (HIGH confidence)
|
||||
- [Striim: 7 Must-Have Features of Modern Data Pipelines](https://www.striim.com/blog/what-is-a-data-pipeline-and-must-have-features-of-modern-data-pipelines/)
|
||||
- [Dagster: Data Pipeline Frameworks Key Features 2025](https://dagster.io/guides/data-pipeline-frameworks-key-features-10-tools-to-know-in-2025)
|
||||
- [Microsoft Azure: AI Agent Orchestration Patterns](https://learn.microsoft.com/en-us/azure/architecture/ai-ml/guide/ai-agent-design-patterns)
|
||||
- [Medium: Idempotency Guide for Data Pipelines](https://medium.com/@QuarkAndCode/idempotency-guide-iac-apis-data-pipelines-temporal-workflows-8d85dc280613) - MEDIUM confidence
|
||||
- [Fivetran: Data Pipeline State Management](https://www.fivetran.com/blog/data-pipeline-state-management-an-underappreciated-challenge) - MEDIUM confidence
|
||||
- PROJECT.md and ARCHITECTURE.md from codebase analysis - HIGH confidence
|
||||
@@ -198,3 +418,4 @@ Based on research, modern data pipeline and workflow orchestration systems have
|
||||
|
||||
*Feature research for: Skill-based Workflow Orchestration (Content Processing)*
|
||||
*Researched: 2026-03-13*
|
||||
*Updated for v1.3 Anti-Crawler: 2026-03-18*
|
||||
|
||||
+423
-58
@@ -1,12 +1,14 @@
|
||||
# Pitfalls Research
|
||||
|
||||
**Domain:** Skill-based Workflow Orchestration (LLM Agent Pipeline)
|
||||
**Researched:** 2026-03-13
|
||||
**Confidence:** HIGH
|
||||
**Researched:** 2026-03-13 (Original), 2026-03-18 (Anti-Crawler Update)
|
||||
**Confidence:** HIGH (Pipeline), MEDIUM (Anti-Crawler)
|
||||
|
||||
---
|
||||
|
||||
## Critical Pitfalls
|
||||
## Part 1: Pipeline Architecture Pitfalls (v1.0-1.2)
|
||||
|
||||
> 以下陷阱适用于管道架构本身,已在 v1.0-1.2 中解决。
|
||||
|
||||
### Pitfall 1: Statelessness = Restart from Scratch
|
||||
|
||||
@@ -91,52 +93,43 @@ Phase 1 (PIPE-03: 统一 JSON Schema, PIPE-06: 清晰的流程定义)
|
||||
**How to avoid:**
|
||||
- 对于这个项目:**串行执行**。每个步骤完成后才开始下一个
|
||||
- 如果未来需要并行:使用文件锁、状态锁、或任务队列
|
||||
- 明确定义哪些资源是共享的,哪些步骤可以并行
|
||||
|
||||
**Warning signs:**
|
||||
- 偶发的"文件不存在"或"文件损坏"错误
|
||||
- 状态文件内容不符合预期
|
||||
- 同一时间大量 API 调用导致限流
|
||||
|
||||
**Phase to address:**
|
||||
Phase 1 (设计文档中明确:串行执行模式)
|
||||
Phase 1 (设计决策:串行执行模式)
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 5: "Automating Bad Processes"
|
||||
|
||||
**What goes wrong:**
|
||||
手动流程本身有问题(不清晰、有冗余、有错误),自动化只是让错误发生得更快。例如:元数据提取逻辑有 bug,自动化后每个视频都提取错误信息。
|
||||
在流程本身有问题时,自动化只是让错误发生得更快。例如:Whisper 识别质量差(没有后处理),自动化后产出大量低质量文本。
|
||||
|
||||
**Why it happens:**
|
||||
急于自动化,没有先验证和优化手动流程。"先写代码再说"的心态。
|
||||
急于自动化,没有先验证手动流程的正确性。"先跑起来再说"的心态。
|
||||
|
||||
**How to avoid:**
|
||||
- 先手动执行完整流程一次,记录每一步
|
||||
- 验证每个步骤的输出是否符合预期
|
||||
- 修复流程问题后再自动化
|
||||
- 每个步骤有明确的成功标准,不只是"没有报错"
|
||||
- **先手动执行完整流程,确保每步输出符合预期**
|
||||
- 验证流程正确后再自动化
|
||||
- 每个步骤有明确的成功标准
|
||||
|
||||
**Warning signs:**
|
||||
- 自动化后发现输出质量不如手动
|
||||
- 需要频繁修改代码来"修复"流程
|
||||
- 用户仍然需要手动检查和修正输出
|
||||
- 自动化后输出质量下降
|
||||
- 需要"后处理"来修复自动化输出
|
||||
|
||||
**Phase to address:**
|
||||
Phase 1 之前:手动验证流程 (PROJECT.md 中已验证的技能列表)
|
||||
Phase 0 (验证阶段) - 在自动化之前验证
|
||||
|
||||
---
|
||||
|
||||
### Pitfall 6: Environment Variable Sprawl
|
||||
|
||||
**What goes wrong:**
|
||||
环境变量分散在多个地方:`~/.kb_env`、子技能自己的配置、HF_TOKEN 在子章节、ZHIHU_COOKIE 在另一个文件。配置遗漏或冲突时,错误难以定位。
|
||||
配置分散在多个地方:`~/.kb_env`、`HF_TOKEN`、`ZHIHU_COOKIE`、环境变量。用户不知道需要配置什么,"在我的机器上能跑"问题频发。
|
||||
|
||||
**Why it happens:**
|
||||
每个技能独立开发,各自管理配置。没有统一的配置策略。
|
||||
不同功能由不同时间添加,没有统一的配置管理。
|
||||
|
||||
**How to avoid:**
|
||||
- 所有环境变量集中在一个文件 (`~/.kb_env`)
|
||||
- 工作流启动时检查所有必需变量,缺失则报错退出
|
||||
- 文档中明确列出所有变量及其用途
|
||||
- 可选变量有明确的默认值和回退策略
|
||||
@@ -175,9 +168,284 @@ Phase 1 (SKILL.md 中的"严格失败处理原则"需要严格执行)
|
||||
|
||||
---
|
||||
|
||||
## Part 2: Anti-Crawler Optimization Pitfalls (v1.3)
|
||||
|
||||
> 以下陷阱适用于 v1.3 反爬虫优化里程碑,重点关注代理轮换、行为伪装、验证码处理、错误恢复等。
|
||||
|
||||
### Pitfall AC-1: IP 泄漏 - 代理配置不完整导致真实 IP 暴露
|
||||
|
||||
**What goes wrong:**
|
||||
使用了代理但仍然暴露真实 IP,导致被目标平台封禁。常见于:
|
||||
- 只配置了 HTTP 代理但未配置 HTTPS 代理
|
||||
- Session 对象未正确绑定代理,部分请求绕过代理
|
||||
- DNS 泄漏:DNS 查询未通过代理直接解析
|
||||
- WebSocket 连接未走代理
|
||||
|
||||
**Why it happens:**
|
||||
开发者通常只关注主要请求的代理配置,忽略了:
|
||||
1. 系统环境变量可能覆盖代码中的代理设置
|
||||
2. `requests.Session` 默认 `trust_env=True`,可能使用系统代理而非指定代理
|
||||
3. Playwright 的 `proxy` 配置需要同时覆盖 HTTP/HTTPS
|
||||
|
||||
**How to avoid:**
|
||||
```python
|
||||
# Playwright 正确配置
|
||||
context_options = {
|
||||
"proxy": {
|
||||
"server": "http://proxy.example.com:8080",
|
||||
# 确保同时处理 HTTPS
|
||||
}
|
||||
}
|
||||
|
||||
# requests Session 正确配置
|
||||
session = requests.Session()
|
||||
session.trust_env = False # 关键:禁用系统代理干扰
|
||||
session.proxies = {
|
||||
"http": proxy_url,
|
||||
"https": proxy_url, # 必须同时配置
|
||||
}
|
||||
```
|
||||
|
||||
**Warning signs:**
|
||||
- 使用代理后仍然收到 403 错误
|
||||
- 目标平台显示你的真实地理位置
|
||||
- IP 检测 API 返回真实 IP 而非代理 IP
|
||||
|
||||
**Phase to address:** Phase 1 (AC-01: 代理池管理)
|
||||
|
||||
---
|
||||
|
||||
### Pitfall AC-2: 代理轮换模式过于规律被识别
|
||||
|
||||
**What goes wrong:**
|
||||
虽然使用了代理轮换,但因为轮换间隔固定、顺序可预测,被平台识别为自动化行为。表现为:
|
||||
- 每次请求后立即切换 IP
|
||||
- 代理使用顺序固定 (A→B→C→A→B→C)
|
||||
- 所有代理来自同一 IP 段或同一数据中心
|
||||
|
||||
**Why it happens:**
|
||||
开发者追求简单实现,使用 `itertools.cycle()` 或简单的取模轮换,忽略了反爬系统会检测:
|
||||
1. IP 变化模式
|
||||
2. 请求时间分布
|
||||
3. 代理 IP 的 ASN (自治系统号) 分布
|
||||
|
||||
**How to avoid:**
|
||||
```python
|
||||
import random
|
||||
|
||||
class ProxyPool:
|
||||
def get_proxy(self) -> str:
|
||||
# 随机选择而非顺序轮换
|
||||
return random.choice(self.healthy_proxies)
|
||||
|
||||
def should_rotate(self) -> bool:
|
||||
# 随机化轮换时机,而非每次请求都轮换
|
||||
return random.random() < self.rotation_probability
|
||||
```
|
||||
|
||||
**Better approach:**
|
||||
- 使用加权随机选择,健康度高的代理获得更多请求
|
||||
- 同一会话内保持 IP 稳定,仅在检测到风险或达到请求阈值时轮换
|
||||
- 混合使用住宅代理和数据中心代理
|
||||
|
||||
**Warning signs:**
|
||||
- 新代理 IP 很快被封
|
||||
- 收到大量 CAPTCHA 挑战
|
||||
- 平台返回"请求过于频繁"错误
|
||||
|
||||
**Phase to address:** Phase 1 (AC-01: 代理池管理)
|
||||
|
||||
---
|
||||
|
||||
### Pitfall AC-3: 验证码检测缺失导致无限阻塞
|
||||
|
||||
**What goes wrong:**
|
||||
爬虫遇到验证码页面后:
|
||||
- 继续发送请求,被持续拒绝
|
||||
- 无限重试,消耗所有代理资源
|
||||
- 没有任何告警,任务静默失败
|
||||
|
||||
**Why it happens:**
|
||||
开发者假设请求成功返回 200 就代表正常,忽略了:
|
||||
1. 验证码页面可能返回 200 状态码
|
||||
2. Cloudflare/DataDome 等服务返回"假"的正常响应
|
||||
3. 平台使用 JavaScript 渲染验证码,API 拦截无法检测
|
||||
|
||||
**How to avoid:**
|
||||
```python
|
||||
# 验证码检测逻辑
|
||||
CAPTCHA_INDICATORS = [
|
||||
"captcha", "verify", "验证", "人机验证",
|
||||
"cf-browser-verification", "challenge-platform",
|
||||
]
|
||||
|
||||
def detect_captcha(html_content: str, url: str) -> bool:
|
||||
content_lower = html_content.lower()
|
||||
return any(indicator in content_lower for indicator in CAPTCHA_INDICATORS)
|
||||
|
||||
# Playwright 中检测
|
||||
def check_for_captcha(page) -> bool:
|
||||
captcha_selectors = [
|
||||
"iframe[src*='captcha']",
|
||||
".captcha-container",
|
||||
"#captcha",
|
||||
"div[class*='verify']",
|
||||
]
|
||||
for selector in captcha_selectors:
|
||||
if page.locator(selector).count() > 0:
|
||||
return True
|
||||
return False
|
||||
```
|
||||
|
||||
**Response strategy when detected:**
|
||||
1. 立即停止当前任务
|
||||
2. 记录触发验证码的 URL 和代理
|
||||
3. 将该代理标记为"风险"
|
||||
4. 通知用户(对于个人知识库场景,等待人工介入是合理的)
|
||||
|
||||
**Warning signs:**
|
||||
- 响应内容突然变短或为空
|
||||
- 响应 HTML 包含验证码相关关键词
|
||||
- 页面跳转到验证码 URL
|
||||
|
||||
**Phase to address:** Phase 2 (AC-02: 请求行为伪装) + Phase 3 (AC-03: 验证码检测)
|
||||
|
||||
---
|
||||
|
||||
### Pitfall AC-4: 重试策略不区分错误类型
|
||||
|
||||
**What goes wrong:**
|
||||
对所有错误使用相同的重试策略:
|
||||
- 404 Not Found 也在重试
|
||||
- 401 Unauthorized 无限重试
|
||||
- 429 Rate Limit 重试间隔过短
|
||||
|
||||
**Why it happens:**
|
||||
使用统一的重试装饰器,未针对不同 HTTP 状态码制定策略。现有代码 `retry_on_network_error` 只处理 `NetworkError`,但错误分类不够细致。
|
||||
|
||||
**How to avoid:**
|
||||
```python
|
||||
# 错误分类策略
|
||||
ERROR_STRATEGIES = {
|
||||
# 永不重试
|
||||
400: "no_retry", # Bad Request - 修复请求
|
||||
401: "no_retry", # Unauthorized - 需要 Cookie 更新
|
||||
403: "switch_proxy", # Forbidden - 可能是 IP 封禁
|
||||
404: "no_retry", # Not Found - 资源不存在
|
||||
|
||||
# 有限重试
|
||||
429: "slow_retry", # Rate Limit - 长间隔重试
|
||||
499: "retry", # Client Closed - 可重试
|
||||
|
||||
# 正常重试
|
||||
500: "retry", # Internal Server Error
|
||||
502: "retry", # Bad Gateway
|
||||
503: "retry", # Service Unavailable
|
||||
504: "retry", # Gateway Timeout
|
||||
}
|
||||
```
|
||||
|
||||
**For 429 Rate Limit specifically:**
|
||||
```python
|
||||
# 尊重 Retry-After 响应头
|
||||
def handle_429(response):
|
||||
retry_after = response.headers.get("Retry-After")
|
||||
if retry_after:
|
||||
wait_time = int(retry_after)
|
||||
else:
|
||||
wait_time = 60 # 默认等待 60 秒
|
||||
time.sleep(wait_time)
|
||||
```
|
||||
|
||||
**Warning signs:**
|
||||
- 重试日志显示相同的 401/404 错误重复出现
|
||||
- 重试次数很快耗尽但问题未解决
|
||||
- 代理池快速耗尽
|
||||
|
||||
**Phase to address:** Phase 4 (AC-04: 错误恢复机制增强)
|
||||
|
||||
---
|
||||
|
||||
### Pitfall AC-5: 请求间隔过于规律被识别为机器人
|
||||
|
||||
**What goes wrong:**
|
||||
使用固定间隔(如每 2 秒一个请求)被反爬系统识别:
|
||||
- 间隔时间完全相同
|
||||
- 请求时间戳呈现明显的周期性
|
||||
- 24 小时请求分布不自然(凌晨也高频请求)
|
||||
|
||||
**Why it happens:**
|
||||
开发者使用 `time.sleep(2)` 实现简单的限流,但:
|
||||
1. 固定间隔是机器人行为的典型特征
|
||||
2. 真实用户行为具有随机性
|
||||
3. 现有代码 `random.uniform(min_delay, max_delay)` 是正确方向,但范围可能需要调整
|
||||
|
||||
**How to avoid:**
|
||||
```python
|
||||
import random
|
||||
import time
|
||||
|
||||
class BehaviorSimulator:
|
||||
def __init__(self):
|
||||
self.base_interval = 2.0
|
||||
self.jitter_range = 1.0
|
||||
|
||||
def get_next_delay(self) -> float:
|
||||
# 基础间隔 + 随机抖动
|
||||
jitter = random.uniform(-self.jitter_range, self.jitter_range)
|
||||
delay = self.base_interval + jitter
|
||||
|
||||
# 偶尔插入较长暂停(模拟阅读时间)
|
||||
if random.random() < 0.1: # 10% 概率
|
||||
delay += random.uniform(5, 15)
|
||||
|
||||
return max(0.5, delay) # 保证最小间隔
|
||||
```
|
||||
|
||||
**Warning signs:**
|
||||
- 使用随机间隔后成功率显著提升
|
||||
- 平台开始频繁要求验证码
|
||||
|
||||
**Phase to address:** Phase 2 (AC-02: 请求行为伪装)
|
||||
|
||||
---
|
||||
|
||||
### Pitfall AC-6: 指数退避无 Jitter 导致重试风暴
|
||||
|
||||
**What goes wrong:**
|
||||
多个爬虫实例同时遇到错误时,因为退避时间相同,会在同一时刻重试,导致"重试风暴"。
|
||||
|
||||
**Why it happens:**
|
||||
标准指数退避算法:`wait = base * 2^attempt`,所有实例计算结果相同。
|
||||
|
||||
**How to avoid:**
|
||||
```python
|
||||
# 正确:指数退避 + 随机抖动
|
||||
def get_backoff_with_jitter(attempt: int, base: float = 1.0) -> float:
|
||||
exponential = base * (2 ** attempt)
|
||||
jitter = random.uniform(0, exponential * 0.5) # 0-50% 抖动
|
||||
return exponential + jitter
|
||||
|
||||
# tenacity 配置
|
||||
from tenacity import wait_exponential_jitter
|
||||
|
||||
retry_decorator = retry(
|
||||
wait=wait_exponential_jitter(initial=1, max=60, jitter=5),
|
||||
stop=stop_after_attempt(3),
|
||||
)
|
||||
```
|
||||
|
||||
**Warning signs:**
|
||||
- 服务恢复瞬间流量激增
|
||||
- 错误在固定时间间隔后重复出现
|
||||
|
||||
**Phase to address:** Phase 4 (AC-04: 错误恢复机制增强)
|
||||
|
||||
---
|
||||
|
||||
## Technical Debt Patterns
|
||||
|
||||
Shortcuts that seem reasonable but create long-term problems.
|
||||
### Pipeline Technical Debt
|
||||
|
||||
| Shortcut | Immediate Benefit | Long-term Cost | When Acceptable |
|
||||
|----------|-------------------|----------------|-----------------|
|
||||
@@ -188,11 +456,21 @@ Shortcuts that seem reasonable but create long-term problems.
|
||||
| 跳过错误处理 | 节省开发时间 | 生产环境频繁崩溃 | 仅限原型/POC |
|
||||
| 不记录中间结果 | 节省存储 | 无法断点续传,无法审计 | 仅限幂等操作 |
|
||||
|
||||
### Anti-Crawler Technical Debt
|
||||
|
||||
| Shortcut | Immediate Benefit | Long-term Cost | When Acceptable |
|
||||
|----------|-------------------|----------------|-----------------|
|
||||
| 硬编码单个代理 | 快速实现 | 单点故障,被封即全部失败 | 仅开发测试阶段 |
|
||||
| 固定请求间隔 | 代码简单 | 被识别为机器人 | **永不可接受** |
|
||||
| 忽略 4xx 错误重试 | 减少代码量 | 永久性错误无限重试 | **永不可接受** |
|
||||
| 不验证代理可用性 | 启动快 | 运行时大量失败请求 | 仅 MVP 演示 |
|
||||
| 禁用 SSL 验证 | 解决证书问题 | 安全风险,可能被中间人攻击 | **永不可接受** |
|
||||
|
||||
---
|
||||
|
||||
## Integration Gotchas
|
||||
|
||||
Common mistakes when connecting to external services.
|
||||
### Pipeline Integration
|
||||
|
||||
| Integration | Common Mistake | Correct Approach |
|
||||
|-------------|----------------|------------------|
|
||||
@@ -203,11 +481,21 @@ Common mistakes when connecting to external services.
|
||||
| 知乎 | Cookie 过期导致失败 | 明确错误消息,提示用户更新 Cookie |
|
||||
| Git 归档 | 没有配置用户信息 | 检查 KB_GIT_USER/EMAIL,缺失则跳过 Git |
|
||||
|
||||
### Anti-Crawler Integration (v1.3)
|
||||
|
||||
| Integration Point | Common Mistake | Correct Approach |
|
||||
|-------------------|----------------|------------------|
|
||||
| `ZhihuCrawler` 代理配置 | 只设置 `proxy_required=True` 但不处理代理缺失 | 默认 `False`,显式配置时才强制要求 |
|
||||
| `CrawlerConfig.from_env()` | 假设环境变量一定存在 | 提供默认值和清晰的错误提示 |
|
||||
| `retry_on_network_error` 装饰器 | 对所有函数使用同一重试策略 | 按错误类型区分策略 |
|
||||
| Playwright 浏览器管理 | 每次请求创建新浏览器 | 复用浏览器实例,仅在必要时重建 |
|
||||
| Cookie 管理 | 硬编码 Cookie 有效期 | 实现过期检测和自动刷新 |
|
||||
|
||||
---
|
||||
|
||||
## Performance Traps
|
||||
|
||||
Patterns that work at small scale but fail as usage grows.
|
||||
### Pipeline Performance
|
||||
|
||||
| Trap | Symptoms | Prevention | When It Breaks |
|
||||
|------|----------|------------|----------------|
|
||||
@@ -216,52 +504,107 @@ Patterns that work at small scale but fail as usage grows.
|
||||
| 单次下载整个视频 | 网络超时,下载失败 | 分块下载,支持断点续传 | 大于 500MB 的视频 |
|
||||
| 无限制重试 | 无限循环,资源浪费 | 最大重试次数 + 总超时时间 | 任何外部服务调用 |
|
||||
|
||||
### Anti-Crawler Performance
|
||||
|
||||
| Trap | Symptoms | Prevention | When It Breaks |
|
||||
|------|----------|------------|----------------|
|
||||
| 每次请求验证代理 | 请求延迟显著增加 | 后台异步验证,缓存结果 | >100 代理 |
|
||||
| 过于频繁的代理轮换 | 代理池快速耗尽 | 基于会话而非请求轮换 | >10 QPS |
|
||||
| 无限制的重试 | 任务永远不结束 | 设置最大重试次数和总超时 | 任何规模 |
|
||||
| 同步等待验证码 | 线程阻塞 | 异步检测 + 用户通知 | 任何规模 |
|
||||
|
||||
---
|
||||
|
||||
## Security Mistakes
|
||||
|
||||
Domain-specific security issues beyond general web security.
|
||||
### Pipeline Security
|
||||
|
||||
| Mistake | Risk | Prevention |
|
||||
|---------|------|------------|
|
||||
| API Key 硬编码 | 泄露到 Git 仓库 | 使用环境变量,.gitignore 排除配置文件 |
|
||||
| Cookie 明文存储 | 账号被盗风险 | 提醒用户 Cookie 敏感性,不记录到日志 |
|
||||
| 用户输入直接拼接到命令 | 命令注入 | 验证输入格式,使用参数化调用 |
|
||||
| 日志记录敏感信息 | 信息泄露 | 过滤 API Key、Cookie 等敏感字段 |
|
||||
| Cookie 明文存储 | 会话劫持 | 提醒用户 Cookie 敏感性,不提交到 Git |
|
||||
|
||||
### Anti-Crawler Security
|
||||
|
||||
| Mistake | Risk | Prevention |
|
||||
|---------|------|------------|
|
||||
| 代理凭证明文存储 | 凭证泄露 | 使用环境变量,支持 Secret 类型 |
|
||||
| 日志输出完整 Cookie | 会话劫持 | 日志脱敏,仅显示前几位 |
|
||||
| 忽略 HTTPS 证书验证 | 中间人攻击 | **永不跳过证书验证** |
|
||||
| 代理 URL 包含密码 | 密码泄露 | 分离 server/username/password |
|
||||
|
||||
---
|
||||
|
||||
## Platform-Specific Pitfalls
|
||||
|
||||
### 知乎 (Zhihu) 反爬特性
|
||||
|
||||
| 特性 | 说明 | 应对策略 |
|
||||
|------|------|----------|
|
||||
| `x-zse-96` 签名 | 动态签名验证 | 使用 Playwright 浏览器自动处理(现有方案正确) |
|
||||
| Cookie 过期检测 | `z_c0` Cookie 有效期约 7 天 | 实现过期检测,触发重新登录 |
|
||||
| 登录状态验证 | 未登录时重定向到登录页 | 检测重定向,触发 Cookie 刷新 |
|
||||
| 请求频率敏感 | 短时间大量请求触发验证码 | 严格控制请求间隔(2-5秒) |
|
||||
| IP 地理位置检测 | 异常地理位置可能触发验证 | 使用国内代理 |
|
||||
|
||||
### B站 (Bilibili) 反爬特性
|
||||
|
||||
| 特性 | 说明 | 应对策略 |
|
||||
|------|------|----------|
|
||||
| 滑动验证码 | 高频访问触发 | 降低频率,使用代理轮换 |
|
||||
| 多维度检测 | User-Agent、Cookie、IP 综合判断 | 保持指纹一致性 |
|
||||
| 登录必要性 | 部分内容需要登录 | Cookie 持久化管理 |
|
||||
| API 限流 | 单 IP 请求频率限制 | 代理轮换 + 请求间隔 |
|
||||
|
||||
---
|
||||
|
||||
## "Looks Done But Isn't" Checklist
|
||||
|
||||
Things that appear complete but are missing critical pieces.
|
||||
### Pipeline Checklist (v1.0-1.2)
|
||||
|
||||
- [ ] **State Management:** Often missing `workflow_state.json` — verify 状态文件在每个步骤后更新
|
||||
- [ ] **Error Handling:** Often missing 可重试/不可重试区分 — verify 错误消息包含可操作建议
|
||||
- [ ] **Schema Validation:** Often missing 输出验证 — verify 每个步骤输出符合定义的 Schema
|
||||
- [ ] **Environment Check:** Often missing 启动前检查 — verify 工作流开始时验证所有必需变量
|
||||
- [ ] **Success Criteria:** Often missing 明确标准 — verify 每个步骤有可验证的成功条件
|
||||
- [ ] **Resume Capability:** Often missing 断点续传 — verify 中断后可以从最后完成步骤继续
|
||||
- [ ] **Idempotency:** Often missing 幂等保证 — verify 重复执行不产生重复文件
|
||||
- [ ] **状态管理:** 是否每个步骤完成后写入状态?中断后能否恢复?
|
||||
- [ ] **错误上下文:** 错误消息是否包含步骤名、输入摘要、可操作建议?
|
||||
- [ ] **Schema 验证:** 每个步骤输入/输出是否通过 Pydantic 验证?
|
||||
- [ ] **幂等性:** 重复执行同一链接是否产生相同结果?
|
||||
- [ ] **环境变量:** 启动时是否检查所有必需变量?
|
||||
|
||||
### Anti-Crawler Checklist (v1.3)
|
||||
|
||||
- [ ] **代理池:** 是否验证代理实际可用性?是否测试代理 IP 检测?
|
||||
- [ ] **请求间隔:** 是否添加随机抖动?是否模拟人类行为?
|
||||
- [ ] **验证码检测:** 是否检测所有常见验证码类型?是否有处理流程?
|
||||
- [ ] **错误恢复:** 是否区分可重试/不可重试错误?是否有最大重试限制?
|
||||
- [ ] **Cookie 管理:** 是否检测过期?是否支持自动刷新?
|
||||
- [ ] **日志脱敏:** 是否避免在日志中输出完整 Cookie/密码?
|
||||
- [ ] **集成测试:** 是否测试与现有 Pipeline 的兼容性?
|
||||
|
||||
---
|
||||
|
||||
## Recovery Strategies
|
||||
|
||||
When pitfalls occur despite prevention, how to recover.
|
||||
### Pipeline Recovery
|
||||
|
||||
| Pitfall | Recovery Cost | Recovery Steps |
|
||||
|---------|---------------|----------------|
|
||||
| 无状态导致重新执行 | HIGH | 1. 识别已完成的步骤(通过输出文件) 2. 手动创建状态文件 3. 从断点继续 |
|
||||
| 错误上下文丢失 | MEDIUM | 1. 检查所有输出文件 2. 重新执行失败的步骤(带详细日志) 3. 对比成功和失败案例 |
|
||||
| 配置分散导致问题 | LOW | 1. 创建统一的 ~/.kb_env 2. 迁移所有配置 3. 验证每个技能 |
|
||||
| 并发问题 | MEDIUM | 1. 停止所有执行 2. 清理临时文件 3. 串行重新执行 |
|
||||
| 降级处理不当 | LOW | 1. 删除无效输出 2. 修复根本问题 3. 重新执行 |
|
||||
| Statelessness | HIGH | 重新实现状态管理,迁移现有数据 |
|
||||
| Error Context Lost | MEDIUM | 增强错误处理,更新所有步骤 |
|
||||
| Schema Mismatch | MEDIUM | 更新 Schema,迁移现有数据 |
|
||||
|
||||
### Anti-Crawler Recovery
|
||||
|
||||
| Pitfall | Recovery Cost | Recovery Steps |
|
||||
|---------|---------------|----------------|
|
||||
| IP 泄漏 | HIGH | 1. 停止所有爬虫 2. 更换代理池 3. 等待封禁解除 |
|
||||
| 代理轮换被识别 | MEDIUM | 1. 更换代理提供商 2. 调整轮换策略 3. 增加请求间隔 |
|
||||
| 验证码检测缺失 | LOW | 1. 添加检测逻辑 2. 清理被污染的代理 3. 重新开始任务 |
|
||||
| 重试策略错误 | LOW | 1. 修改错误分类 2. 清理重试队列 3. 重新执行 |
|
||||
| Cookie 过期 | LOW | 1. 触发重新登录 2. 更新 Cookie 3. 继续任务 |
|
||||
|
||||
---
|
||||
|
||||
## Pitfall-to-Phase Mapping
|
||||
|
||||
How roadmap phases should address these pitfalls.
|
||||
### Pipeline Phases (v1.0-1.2)
|
||||
|
||||
| Pitfall | Prevention Phase | Verification |
|
||||
|---------|------------------|--------------|
|
||||
@@ -273,23 +616,24 @@ How roadmap phases should address these pitfalls.
|
||||
| Environment Variable Sprawl | Phase 1 (环境检查) | 启动时验证所有必需变量,缺失则报错 |
|
||||
| Graceful Degradation That Isn't | Phase 1 (失败处理原则) | 关键步骤失败 = 整体失败,不假装成功 |
|
||||
|
||||
---
|
||||
### Anti-Crawler Phases (v1.3)
|
||||
|
||||
## Phase-Specific Warnings
|
||||
|
||||
| Phase Topic | Likely Pitfall | Mitigation |
|
||||
|-------------|---------------|------------|
|
||||
| 管道模型定义 | 步骤边界模糊 | 明确定义每个步骤的输入、输出、前置条件 |
|
||||
| 状态管理实现 | 状态格式不一致 | 使用统一的 JSON Schema |
|
||||
| Schema 设计 | 过于复杂或过于简单 | 从现有输出反推,迭代优化 |
|
||||
| 幂等实现 | 判断"已存在"的逻辑有漏洞 | 使用内容哈希或唯一标识符 |
|
||||
| 错误恢复 | 重试导致无限循环 | 设置最大重试次数和总超时 |
|
||||
| 代码重构 | 破坏现有功能 | 先写测试,小步重构 |
|
||||
| Pitfall | Prevention Phase | Verification |
|
||||
|---------|------------------|--------------|
|
||||
| IP 泄漏 | Phase 1 (AC-01: 代理池管理) | 使用 IP 检测 API 验证代理生效 |
|
||||
| 代理轮换规律 | Phase 1 (AC-01: 代理池管理) | 分析日志确认轮换随机性 |
|
||||
| 验证码检测缺失 | Phase 3 (AC-03: 验证码检测) | 人工触发验证码测试检测逻辑 |
|
||||
| 重试策略错误 | Phase 4 (AC-04: 错误恢复) | 模拟各类错误验证处理正确 |
|
||||
| 请求间隔规律 | Phase 2 (AC-02: 行为伪装) | 统计分析请求时间分布 |
|
||||
| 退避无 Jitter | Phase 4 (AC-04: 错误恢复) | 多实例并发测试验证无风暴 |
|
||||
| 平台特性适配 | Phase 5 (AC-05: 知乎) + Phase 6 (AC-06: B站) | 实际平台测试 |
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
|
||||
### Pipeline Sources (v1.0-1.2)
|
||||
|
||||
- [AI Agent Anti-Patterns: Architectural Pitfalls](https://achan2013.medium.com/ai-agent-anti-patterns-part-1-architectural-pitfalls-that-break-enterprise-agents-before-they-32d211dded43) - MEDIUM confidence
|
||||
- [Demystifying Failures in Platform-Orchestrated Workflows](https://arxiv.org/html/2509.23735v2) - HIGH confidence
|
||||
- [10 Reasons Multi-Agent Workflows Fail](https://www.infoq.com/presentations/multi-agent-workflow/) - MEDIUM confidence
|
||||
@@ -305,6 +649,27 @@ How roadmap phases should address these pitfalls.
|
||||
- [AI Agent 工作流设计的5 个反模式](https://www.moltbook.com/post/f826b987-641d-4bb5-9938-b825ac5a6b13) - MEDIUM confidence
|
||||
- [Workflow Process Automation Gone Wrong](https://www.flowwright.com/workflow-process-automation-gone-wrong-lessons-learned) - MEDIUM confidence
|
||||
|
||||
### Anti-Crawler Sources (v1.3)
|
||||
|
||||
**高可信度来源 (官方文档/权威技术文章):**
|
||||
- [Firecrawl: 10 Common Web-Scraping Mistakes](https://www.firecrawl.dev/blog/web-scraping-mistakes-and-fixes) - 代理轮换和错误处理最佳实践
|
||||
- [ZenRows: Python Requests Retry](https://www.zenrows.com/blog/python-requests-retry) - 指数退避实现
|
||||
- [Tenacity Documentation](https://tenacity.readthedocs.io/) - Python 重试库官方文档
|
||||
|
||||
**中等可信度来源 (技术博客/社区):**
|
||||
- [CSDN: 爬虫 Cookie 关键点](https://blog.csdn.net/QuickCode/article/details/153689079) - 请求间隔和 Cookie 处理
|
||||
- [知乎专栏: 反反爬虫方法](https://zhuanlan.zhihu.com/p/461669530) - 请求头构造
|
||||
- [Stack Overflow: requests proxy bypass](https://stackoverflow.com/questions/28521535/requests-how-to-disable-bypass-proxy) - `trust_env=False` 防止代理泄漏
|
||||
|
||||
**平台特性 (社区经验):**
|
||||
- [CSDN问答: B站反爬虫机制](https://ask.csdn.net/questions/9093164) - B站多维度检测
|
||||
- [知乎专栏: 代理IP爬取Bilibili](https://zhuanlan.zhihu.com/p/1888190028963872900) - B站 IP 检测和频率限制
|
||||
|
||||
**现有代码分析:**
|
||||
- `kb_workflow/crawler/zhihu_crawler.py` - 现有知乎爬虫实现
|
||||
- `kb_workflow/crawler/config.py` - 现有配置结构
|
||||
- `kb_workflow/pipeline/retry.py` - 现有重试机制
|
||||
|
||||
---
|
||||
*Pitfalls research for: Skill-based Workflow Orchestration*
|
||||
*Researched: 2026-03-13*
|
||||
*Pitfalls research for: Skill-based Workflow Orchestration + Anti-Crawler Optimization*
|
||||
*Researched: 2026-03-13 (Pipeline), 2026-03-18 (Anti-Crawler)*
|
||||
|
||||
+171
-10
@@ -1,7 +1,7 @@
|
||||
# Stack Research
|
||||
|
||||
**Domain:** Skill-based Workflow Orchestration System (Python)
|
||||
**Researched:** 2026-03-13
|
||||
**Researched:** 2026-03-18 (Updated for v1.3 Anti-Crawler)
|
||||
**Confidence:** HIGH
|
||||
|
||||
## Recommended Stack
|
||||
@@ -17,14 +17,23 @@
|
||||
| **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);支持指数退避、条件重试 |
|
||||
| **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
|
||||
|
||||
@@ -43,12 +52,35 @@ 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 过于重量级 |
|
||||
@@ -68,6 +100,10 @@ uv add --dev pytest pytest-cov ruff
|
||||
| **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
|
||||
|
||||
@@ -86,6 +122,11 @@ uv add --dev pytest pytest-cov ruff
|
||||
- 生成 Mermaid 或 Graphviz 图表
|
||||
- 因为: 内置支持,无需额外工具
|
||||
|
||||
**If playwright-stealth 被检测 (Phase 2):**
|
||||
- 切换到 camoufox
|
||||
- 配合现有的代理配置
|
||||
- 因为: Firefox 内核更难被指纹识别
|
||||
|
||||
## Version Compatibility
|
||||
|
||||
| Package A | Compatible With | Notes |
|
||||
@@ -93,6 +134,9 @@ uv add --dev pytest pytest-cov ruff
|
||||
| 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
|
||||
|
||||
@@ -149,16 +193,133 @@ def process(link: str, resume: bool = False):
|
||||
# transitions 状态机驱动
|
||||
```
|
||||
|
||||
### v1.3 Anti-Crawler 集成示例
|
||||
|
||||
#### aiolimiter 限流
|
||||
```python
|
||||
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 集成
|
||||
```python
|
||||
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 抖动增强
|
||||
```python
|
||||
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)
|
||||
```
|
||||
|
||||
#### 代理池配置
|
||||
```python
|
||||
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 检测
|
||||
```python
|
||||
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
|
||||
|
||||
- [Pydantic v2.11 Release](https://pydantic.dev/articles/pydantic-v2-11-release) — 版本特性确认 (HIGH confidence)
|
||||
- [Pydantic JSON Schema Docs](https://docs.pydantic.dev/latest/concepts/json_schema/) — JSON Schema 生成能力 (HIGH confidence)
|
||||
- [transitions 0.9.3 on PyPI](https://pypi.org/project/transitions/) — 状态机库详情 (HIGH confidence)
|
||||
- [Prefect vs Dagster Comparison](https://www.prefect.io/compare/dagster) — 编排工具对比 (MEDIUM confidence)
|
||||
- [Python CLI Tools Comparison 2025](https://dasroot.net/posts/2025/12/building-cli-tools-python-click-typer-argparse/) — CLI 框架对比 (MEDIUM confidence)
|
||||
- [uv Official Docs](https://docs.astral.sh/uv/) — 包管理器最佳实践 (HIGH confidence)
|
||||
- [pydantic-settings Guide](https://levelup.gitconnected.com/pydantic-settings-2025-a-clean-way-to-handle-configs-f1c432030085) — 配置管理方案 (MEDIUM confidence)
|
||||
### Core Stack (HIGH confidence)
|
||||
- [Pydantic v2.11 Release](https://pydantic.dev/articles/pydantic-v2-11-release) — 版本特性确认
|
||||
- [Pydantic JSON Schema Docs](https://docs.pydantic.dev/latest/concepts/json_schema/) — JSON Schema 生成能力
|
||||
- [transitions 0.9.3 on PyPI](https://pypi.org/project/transitions/) — 状态机库详情
|
||||
- [uv Official Docs](https://docs.astral.sh/uv/) — 包管理器最佳实践
|
||||
|
||||
### Anti-Crawler (HIGH confidence)
|
||||
- [aiolimiter on PyPI](https://pypi.org/project/aiolimiter/) — asyncio 限流库
|
||||
- [aiolimiter GitHub](https://github.com/mjpieters/aiolimiter) — 文档和示例
|
||||
- [playwright-stealth on PyPI](https://pypi.org/project/playwright-stealth/) — 浏览器隐身库
|
||||
- [playwright-stealth GitHub](https://github.com/AtuboLabs/playwright_stealth) — 源码和使用指南
|
||||
- [camoufox on PyPI](https://pypi.org/project/camoufox/) — Firefox 反检测浏览器
|
||||
- [camoufox GitHub](https://github.com/daijro/camoufox) — 文档和配置选项
|
||||
|
||||
### Comparisons (MEDIUM confidence)
|
||||
- [Prefect vs Dagster Comparison](https://www.prefect.io/compare/dagster) — 编排工具对比
|
||||
- [Python CLI Tools Comparison 2025](https://dasroot.net/posts/2025/12/building-cli-tools-python-click-typer-argparse/) — CLI 框架对比
|
||||
- [pydantic-settings Guide](https://levelup.gitconnected.com/pydantic-settings-2025-a-clean-way-to-handle-configs-f1c432030085) — 配置管理方案
|
||||
- [tenacity wait_random documentation](https://tenacity.readthedocs.io/) — 抖动策略
|
||||
|
||||
---
|
||||
*Stack research for: Skill-based Workflow Orchestration System*
|
||||
*Researched: 2026-03-13*
|
||||
*Researched: 2026-03-13, Updated: 2026-03-18 for v1.3 Anti-Crawler*
|
||||
|
||||
Reference in New Issue
Block a user