fix(09): revise plans based on checker feedback
This commit is contained in:
@@ -0,0 +1,148 @@
|
|||||||
|
---
|
||||||
|
phase: 09-pipeline-integration
|
||||||
|
plan: 00
|
||||||
|
type: execute
|
||||||
|
wave: 0
|
||||||
|
depends_on: []
|
||||||
|
files_modified: []
|
||||||
|
autonomous: true
|
||||||
|
requirements: []
|
||||||
|
user_setup: []
|
||||||
|
|
||||||
|
must_haves:
|
||||||
|
truths:
|
||||||
|
- "测试脚手架已就绪,为 Wave 1 实现提供验证基础"
|
||||||
|
artifacts:
|
||||||
|
- path: "tests/test_platforms/test_zhihu.py"
|
||||||
|
provides: "Test scaffolding for ZhihuAdapter"
|
||||||
|
min_lines: 30
|
||||||
|
exports: ["mock_zhihu_answer_result", "mock_zhihu_zhuanlan_result"]
|
||||||
|
key_links: []
|
||||||
|
---
|
||||||
|
|
||||||
|
<objective>
|
||||||
|
创建 Wave 0 测试脚手架,为后续实现任务提供验证基础。
|
||||||
|
|
||||||
|
Purpose: 遵循 Nyquist 规则,测试先于实现,确保每个实现任务有对应的自动化验证
|
||||||
|
Output: 测试文件骨架和 mock fixtures
|
||||||
|
</objective>
|
||||||
|
|
||||||
|
<execution_context>
|
||||||
|
@/home/starmen1265/.claude/get-shit-done/workflows/execute-plan.md
|
||||||
|
@/home/starmen1265/.claude/get-shit-done/templates/summary.md
|
||||||
|
</execution_context>
|
||||||
|
|
||||||
|
<context>
|
||||||
|
@.planning/PROJECT.md
|
||||||
|
@.planning/ROADMAP.md
|
||||||
|
@.planning/STATE.md
|
||||||
|
@.planning/phases/09-pipeline-integration/09-CONTEXT.md
|
||||||
|
|
||||||
|
<interfaces>
|
||||||
|
From kb_workflow/crawler/models.py:
|
||||||
|
```python
|
||||||
|
class CrawlResult(BaseModel):
|
||||||
|
success: bool
|
||||||
|
content_type: str
|
||||||
|
data: Optional[Union[AnswerData, ArticleData]]
|
||||||
|
comments: Optional[List[CommentData]]
|
||||||
|
error: Optional[str]
|
||||||
|
|
||||||
|
class AnswerData(BaseModel):
|
||||||
|
question_title: str
|
||||||
|
question_description: Optional[str]
|
||||||
|
answer_content: str
|
||||||
|
author: AuthorInfo
|
||||||
|
voteup_count: int
|
||||||
|
comment_count: int
|
||||||
|
created_time: int
|
||||||
|
updated_time: Optional[int]
|
||||||
|
|
||||||
|
class ArticleData(BaseModel):
|
||||||
|
title: str
|
||||||
|
content: str
|
||||||
|
author: AuthorInfo
|
||||||
|
voteup_count: int
|
||||||
|
comment_count: int
|
||||||
|
created_time: int
|
||||||
|
updated_time: Optional[int]
|
||||||
|
|
||||||
|
class CommentData(BaseModel):
|
||||||
|
id: int
|
||||||
|
content: str
|
||||||
|
author: CommentAuthor
|
||||||
|
vote_count: int
|
||||||
|
created_time: int
|
||||||
|
```
|
||||||
|
|
||||||
|
From kb_workflow/auth/zhihu_login.py:
|
||||||
|
```python
|
||||||
|
class ZhihuLoginResult(BaseModel):
|
||||||
|
success: bool
|
||||||
|
cookie_str: Optional[str]
|
||||||
|
error: Optional[str]
|
||||||
|
|
||||||
|
class CookieValidationResult(BaseModel):
|
||||||
|
valid: bool
|
||||||
|
user_id: Optional[str]
|
||||||
|
error: Optional[str]
|
||||||
|
```
|
||||||
|
</interfaces>
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<tasks>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 0: Create test scaffolding and mock fixtures</name>
|
||||||
|
<files>tests/test_platforms/test_zhihu.py</files>
|
||||||
|
<action>
|
||||||
|
创建测试文件骨架,包含以下内容:
|
||||||
|
|
||||||
|
1. Mock fixtures:
|
||||||
|
- `mock_zhihu_answer_result`: 模拟 ZhihuCrawler.crawl_answer() 返回的 CrawlResult
|
||||||
|
- `mock_zhihu_zhuanlan_result`: 模拟 ZhihuCrawler.crawl_article() 返回的 CrawlResult
|
||||||
|
- `mock_comments_list`: 模拟评论列表数据
|
||||||
|
- `mock_zhihu_login_result`: 模拟 ZhihuLogin.login_by_qrcode() 返回结果
|
||||||
|
|
||||||
|
2. 测试用例骨架(使用 pytest.mark.skip 标记,等待实现后移除):
|
||||||
|
- `test_fetch_metadata_answer`: 测试问答元数据获取
|
||||||
|
- `test_fetch_metadata_article`: 测试专栏文章元数据获取
|
||||||
|
- `test_fetch_content_with_comments`: 测试带评论的内容获取
|
||||||
|
- `test_cookie_expired_triggers_login`: 测试 Cookie 过期触发登录
|
||||||
|
- `test_idempotent_execution`: 测试幂等执行
|
||||||
|
- `test_comment_formatting`: 测试评论格式化
|
||||||
|
|
||||||
|
3. Mock 配置:
|
||||||
|
- 使用 pytest-mock 或 unittest.mock
|
||||||
|
- 配置 ZhihuCrawler mock 返回预期的 CrawlResult
|
||||||
|
- 配置 ZhihuLogin mock 返回预期的登录结果
|
||||||
|
|
||||||
|
文件末尾添加注释标记:
|
||||||
|
```python
|
||||||
|
# WAVE_0_COMPLETE: Test scaffolding ready for implementation
|
||||||
|
```
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
<automated>pytest tests/test_platforms/test_zhihu.py --collect-only -q 2>&1 | grep -c "test_"</automated>
|
||||||
|
</verify>
|
||||||
|
<done>
|
||||||
|
测试文件存在,包含至少 6 个测试用例骨架和 4 个 mock fixtures
|
||||||
|
</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
</tasks>
|
||||||
|
|
||||||
|
<verification>
|
||||||
|
测试骨架已创建,测试可以被 pytest 收集(即使被 skip)
|
||||||
|
</verification>
|
||||||
|
|
||||||
|
<success_criteria>
|
||||||
|
- tests/test_platforms/test_zhihu.py 文件存在
|
||||||
|
- 包含 mock fixtures: mock_zhihu_answer_result, mock_zhihu_zhuanlan_result, mock_comments_list, mock_zhihu_login_result
|
||||||
|
- 包含测试骨架: test_fetch_metadata_answer, test_fetch_metadata_article, test_fetch_content_with_comments, test_cookie_expired_triggers_login, test_idempotent_execution, test_comment_formatting
|
||||||
|
- pytest 可以收集到所有测试用例
|
||||||
|
</success_criteria>
|
||||||
|
|
||||||
|
<output>
|
||||||
|
After completion, create `.planning/phases/09-pipeline-integration/09-00-SUMMARY.md`
|
||||||
|
</output>
|
||||||
@@ -3,8 +3,8 @@ phase: 09-pipeline-integration
|
|||||||
plan: 01
|
plan: 01
|
||||||
type: execute
|
type: execute
|
||||||
wave: 1
|
wave: 1
|
||||||
depends_on: []
|
depends_on: [09-00]
|
||||||
files_modified: []
|
files_modified: [kb_workflow/pipeline/platforms/zhihu.py, tests/test_platforms/test_zhihu.py]
|
||||||
autonomous: true
|
autonomous: true
|
||||||
requirements: [PIPE-01, PIPE-02, PIPE-03]
|
requirements: [PIPE-01, PIPE-02, PIPE-03]
|
||||||
user_setup: []
|
user_setup: []
|
||||||
@@ -13,7 +13,8 @@ must_haves:
|
|||||||
truths:
|
truths:
|
||||||
- "知乎链接使用新爬虫处理器,无需手动设置 Cookie"
|
- "知乎链接使用新爬虫处理器,无需手动设置 Cookie"
|
||||||
- "新处理器与现有 Pipeline 架构完全兼容"
|
- "新处理器与现有 Pipeline 架构完全兼容"
|
||||||
- "支持断点续传和幂等执行(与其他处理器行为一致)"
|
- "支持断点续传和幂等执行(与其他处理器行为一致)"
|
||||||
|
- "评论爬取默认开启,评论追加到正文末尾"
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: "kb_workflow/pipeline/platforms/zhihu.py"
|
- path: "kb_workflow/pipeline/platforms/zhihu.py"
|
||||||
provides: "ZhihuAdapter implementation"
|
provides: "ZhihuAdapter implementation"
|
||||||
@@ -21,7 +22,7 @@ must_haves:
|
|||||||
exports: ["ZhihuAdapter"]
|
exports: ["ZhihuAdapter"]
|
||||||
- path: "kb_workflow/crawler/zhihu_crawler.py"
|
- path: "kb_workflow/crawler/zhihu_crawler.py"
|
||||||
provides: "ZhihuCrawler class"
|
provides: "ZhihuCrawler class"
|
||||||
exports: ["ZhihuCrawler", "Crawl_answer", "crawl_article", "crawl_comments"]
|
exports: ["ZhihuCrawler", "crawl_answer", "crawl_article", "crawl_comments"]
|
||||||
- path: "kb_workflow/crawler/models.py"
|
- path: "kb_workflow/crawler/models.py"
|
||||||
provides: "Data models (AnswerData, ArticleData, CommentData, CrawlResult)"
|
provides: "Data models (AnswerData, ArticleData, CommentData, CrawlResult)"
|
||||||
exports: ["AnswerData", "ArticleData", "CommentData", "CommentAuthor", "ContentMetadata", "AuthorInfo", "CrawlResult"]
|
exports: ["AnswerData", "ArticleData", "CommentData", "CommentAuthor", "ContentMetadata", "AuthorInfo", "CrawlResult"]
|
||||||
@@ -30,8 +31,7 @@ must_haves:
|
|||||||
exports: ["ZhihuLogin", "login_by_qrcode", "validate_cookie", "ZhihuLoginResult", "CookieValidationResult"]
|
exports: ["ZhihuLogin", "login_by_qrcode", "validate_cookie", "ZhihuLoginResult", "CookieValidationResult"]
|
||||||
- path: "tests/test_platforms/test_zhihu.py"
|
- path: "tests/test_platforms/test_zhihu.py"
|
||||||
provides: "test coverage for ZhihuAdapter"
|
provides: "test coverage for ZhihuAdapter"
|
||||||
exports: ["ZhihuAdapter", "test_get_content_type_*"]
|
min_lines: 50
|
||||||
min_lines: 50
|
|
||||||
exports: ["mock_zhihu_answer_result", "mock_zhihu_zhuanlan_result"]
|
exports: ["mock_zhihu_answer_result", "mock_zhihu_zhuanlan_result"]
|
||||||
- path: "kb_workflow/pipeline/processors/download.py"
|
- path: "kb_workflow/pipeline/processors/download.py"
|
||||||
provides: "Download processor (consumer of ZhihuAdapter)"
|
provides: "Download processor (consumer of ZhihuAdapter)"
|
||||||
@@ -49,14 +49,19 @@ must_haves:
|
|||||||
to: "ZhihuAdapter._format_comments_section"
|
to: "ZhihuAdapter._format_comments_section"
|
||||||
via: "content append"
|
via: "content append"
|
||||||
pattern: "\\n---\\n## 热门评论"
|
pattern: "\\n---\\n## 热门评论"
|
||||||
|
- from: "ZhihuAdapter.fetch_content"
|
||||||
|
to: "IdempotencyChecker"
|
||||||
|
via: "幂等检查调用"
|
||||||
|
pattern: "idempotency|already_processed"
|
||||||
---
|
---
|
||||||
|
|
||||||
<objective>
|
<objective>
|
||||||
将新爬虫实现整合进现有 Pipeline 架构,替换原有知乎处理器,保持接口兼容性和,支持评论爬取和Cookie 过期自动处理。
|
将新爬虫实现整合进现有 Pipeline 架构,替换原有知乎处理器,保持接口兼容性,支持评论爬取和 Cookie 过期自动处理。
|
||||||
|
|
||||||
Cookie 过期处理
|
Cookie 过期处理:Cookie 过期时自动触发扫码登录,用户扫码后流程继续。
|
||||||
Cookie 过期时自动触发扫码登录,用户扫码后流程继续
|
新爬虫失败时直接报错,不降级到旧版。
|
||||||
新爬虫失败时直接报错,不降级到旧版。
|
评论爬取默认开启,评论追加到正文末尾。
|
||||||
|
幂等执行:通过 IdempotencyChecker 确保同一内容不会重复处理。
|
||||||
</objective>
|
</objective>
|
||||||
|
|
||||||
<execution_context>
|
<execution_context>
|
||||||
@@ -73,7 +78,7 @@ Cookie 过期时自动触发扫码登录,用户扫码后流程继续
|
|||||||
@.planning/phases/09-pipeline-integration/09-RESEARCH.md
|
@.planning/phases/09-pipeline-integration/09-RESEARCH.md
|
||||||
@.planning/phases/09-pipeline-integration/09-CONTEXT.md
|
@.planning/phases/09-pipeline-integration/09-CONTEXT.md
|
||||||
|
|
||||||
@.planning/phases/09-pipeline-integration/09-VALIDATION.md
|
@.planning/phases/09-pipeline-integration/09-00-SUMMARY.md
|
||||||
|
|
||||||
<interfaces>
|
<interfaces>
|
||||||
<!-- Key types and contracts the executor needs. Executor should use these directly - no codebase exploration needed. -->
|
<!-- Key types and contracts the executor needs. Executor should use these directly - no codebase exploration needed. -->
|
||||||
@@ -98,123 +103,194 @@ class PlatformAdapter(ABC):
|
|||||||
pass
|
pass
|
||||||
```
|
```
|
||||||
|
|
||||||
From kb_workflow/crawler/models.py
|
From kb_workflow/crawler/models.py:
|
||||||
```python
|
```python
|
||||||
class CrawlResult(BaseModel):
|
class CrawlResult(BaseModel):
|
||||||
success: bool
|
success: bool
|
||||||
content_type: str
|
content_type: str
|
||||||
data: Optional[Union[AnswerData, ArticleData]]
|
data: Optional[Union[AnswerData, ArticleData]]
|
||||||
comments: Optional[List[commentData]]
|
comments: Optional[List[CommentData]]
|
||||||
error: Optional[str]
|
error: Optional[str]
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
from kb_workflow/crawler/zhihu_crawler.py
|
From kb_workflow/crawler/zhihu_crawler.py:
|
||||||
```python
|
```python
|
||||||
class ZhihuCrawler:
|
class ZhihuCrawler:
|
||||||
def crawl_answer(self, url: str, include_comments: bool = False) -> CrawlResult
|
def crawl_answer(self, url: str, include_comments: bool = False) -> CrawlResult:
|
||||||
...
|
...
|
||||||
|
|
||||||
def crawl_article(self, url: str) -> CrawlResult:
|
def crawl_article(self, url: str) -> CrawlResult:
|
||||||
"""
|
...
|
||||||
|
|
||||||
def crawl_comments(self, content_type: str, content_id: int, include_comments: bool = True) -> CommentsResult:
|
def crawl_comments(self, content_type: str, content_id: int, include_comments: bool = True) -> CommentsResult:
|
||||||
"""
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
from kb_workflow/auth/zhihu_login.py
|
From kb_workflow/auth/zhihu_login.py:
|
||||||
```python
|
```python
|
||||||
class ZhihuLogin:
|
class ZhihuLogin:
|
||||||
def login_by_qrcode(self) -> ZhihuLoginResult
|
def login_by_qrcode(self) -> ZhihuLoginResult:
|
||||||
"""
|
...
|
||||||
def validate_cookie(self, cookie_str: str = None) -> CookieValidationResult
|
|
||||||
"""
|
def validate_cookie(self, cookie_str: str = None) -> CookieValidationResult:
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
From kb_workflow/pipeline/idempotency.py:
|
||||||
|
```python
|
||||||
|
class IdempotencyChecker:
|
||||||
|
def is_processed(self, content_id: str, content_type: str) -> bool:
|
||||||
|
"""检查内容是否已处理"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def mark_processed(self, content_id: str, content_type: str) -> None:
|
||||||
|
"""标记内容已处理"""
|
||||||
|
...
|
||||||
```
|
```
|
||||||
</interfaces>
|
</interfaces>
|
||||||
|
</context>
|
||||||
|
|
||||||
<tasks>
|
<tasks>
|
||||||
|
|
||||||
<task type="auto">
|
<task type="auto" tdd="true">
|
||||||
<name>Task 1: Update ZhihuAdapter to use ZhihuCrawler</name>
|
<name>Task 1: Update ZhihuAdapter to use ZhihuCrawler</name>
|
||||||
<files>kb_workflow/pipeline/platforms/zhihu.py</files>
|
<files>kb_workflow/pipeline/platforms/zhihu.py</files>
|
||||||
|
<behavior>
|
||||||
|
- Test 1: fetch_metadata 返回正确的问答元数据
|
||||||
|
- Test 2: fetch_metadata 返回正确的专栏文章元数据
|
||||||
|
- Test 3: fetch_content 返回带评论的 Markdown 内容
|
||||||
|
- Test 4: Cookie 过期时自动触发扫码登录
|
||||||
|
- Test 5: 幂等检查阻止重复处理同一内容
|
||||||
|
</behavior>
|
||||||
<action>
|
<action>
|
||||||
修改 ZhihuAdapter 类:
|
修改 ZhihuAdapter 类,内部实现使用 ZhihuCrawler 替代 ZhihuPlaywrightExtractor。
|
||||||
|
|
||||||
内部实现",使用 ZhihuCrawler 替代 ZhihuPlaywrightExtractor。
|
保留公共接口不变 (fetch_metadata, fetch_content, get_content_type, get_output_filename)。
|
||||||
|
|
||||||
保留公共接口不变 (fetch_metadata, fetch_content, get_content_type, get_output_filename).
|
**关键决策实现(来自 CONTEXT.md):**
|
||||||
|
1. **评论爬取默认开启**:设置 include_comments=True 作为默认参数
|
||||||
|
2. **评论追加到正文**:修改 _format_with_frontmatter 在 content 末尾追加评论(格式见 CONTEXT.md specifics)
|
||||||
|
3. **幂等执行 (PIPE-03)**:在 fetch_metadata 开头调用 IdempotencyChecker.is_processed(),已处理的内容直接返回缓存结果或跳过
|
||||||
|
|
||||||
具体修改:
|
具体修改:
|
||||||
1. 移除 ZhihuPlaywrightExtractor` 导入,ZhihuCrawler"
|
1. 移除 ZhihuPlaywrightExtractor 导入,添加 ZhihuCrawler 导入
|
||||||
2 添加 `_get_crawler()` 方法创建和管理 ZhihuCrawler 实例
|
2. 添加 `_get_crawler()` 方法创建和管理 ZhihuCrawler 实例
|
||||||
添加 `_crawl_with_crawler()` 方法使用 ZhihuCrawler 进行内容爬取
|
3. 添加 `_crawl_with_crawler()` 方法使用 ZhihuCrawler 进行内容爬取,**include_comments=True 为默认值**
|
||||||
添加 `_convert_crawl_result_to_metadata()` 方法将 CrawlResult 转换为 metadata dict
|
4. 添加 `_convert_crawl_result_to_metadata()` 方法将 CrawlResult 转换为 metadata dict
|
||||||
添加 `_format_comments_section()` 方法格式化评论为 Markdown
|
5. 添加 `_format_comments_section()` 方法格式化评论为 Markdown
|
||||||
添加 `_is_cookie_expired()` 方法检测 Cookie 过期
|
6. **修改 `_format_with_frontmatter()` 方法**:在正文末尾追加评论部分
|
||||||
添加 `_trigger_qrcode_login()` 方法触发扫码登录
|
```python
|
||||||
移除 `_extract_with_playwright` 和 `_get_extractor` 方法(不再需要)
|
def _format_with_frontmatter(self, ...):
|
||||||
2 修改 `_detect_login_page` 方法,基于 CrawlResult 检测登录页面
|
content = base_content
|
||||||
</action>
|
if comments:
|
||||||
|
content += "\n\n---\n\n## 热门评论\n\n" + self._format_comments_section(comments)
|
||||||
|
return content
|
||||||
|
```
|
||||||
|
7. 添加 `_is_cookie_expired()` 方法检测 Cookie 过期
|
||||||
|
8. 添加 `_trigger_qrcode_login()` 方法触发扫码登录
|
||||||
|
9. 添加幂等检查:在处理前调用 IdempotencyChecker.is_processed()
|
||||||
|
10. 移除 `_extract_with_playwright` 和 `_get_extractor` 方法(不再需要)
|
||||||
|
11. 修改 `_detect_login_page` 方法,基于 CrawlResult 检测登录页面
|
||||||
|
</action>
|
||||||
<verify>
|
<verify>
|
||||||
<automated>pytest tests/test_platforms/test_zhihu.py -x -v</automated>
|
<automated>pytest tests/test_platforms/test_zhihu.py -x -v</automated>
|
||||||
</verify>
|
</verify>
|
||||||
<done>
|
<done>
|
||||||
Z ZhihuAdapter 使用 ZhihuCrawler 作为内容获取
|
ZhihuAdapter 使用 ZhihuCrawler 作为内容获取
|
||||||
fetch_metadata 返回包含评论的 CrawlResult
|
fetch_metadata 返回包含评论的 CrawlResult
|
||||||
fetch_content 返回 Markdown 格式内容(含评论追加)
|
fetch_content 返回 Markdown 格式内容(含评论追加,格式为 "---\n## 热门评论")
|
||||||
</done>
|
评论爬取默认开启(include_comments=True)
|
||||||
|
幂等执行通过 IdempotencyChecker 实现
|
||||||
|
</done>
|
||||||
</task>
|
</task>
|
||||||
|
|
||||||
<task type="auto">
|
<task type="auto" tdd="true">
|
||||||
<name>Task 2: Add Cookie expired auto login tests</name>
|
<name>Task 2: Enable test cases and verify Cookie auto login</name>
|
||||||
<files>tests/test_platforms/test_zhihu.py</files>
|
<files>tests/test_platforms/test_zhihu.py</files>
|
||||||
|
<behavior>
|
||||||
|
- Test 1: Cookie 有效时,爬取正常返回数据
|
||||||
|
- Test 2: Cookie 过期时,触发扫码登录流程
|
||||||
|
- Test 3: 触发登录后重试成功
|
||||||
|
- Test 4: mock _trigger_qrcode_login 返回登录失败时正确处理
|
||||||
|
</behavior>
|
||||||
<action>
|
<action>
|
||||||
添加测试用例验证 Cookie 过期时自动触发扫码登录:
|
移除 Wave 0 创建的测试骨架中的 pytest.mark.skip 标记,实现以下测试场景:
|
||||||
测试场景:
|
|
||||||
1. Cookie 有效时,爬取正常返回数据
|
1. `test_cookie_valid_returns_data`: Cookie 有效时,爬取正常返回数据
|
||||||
2. Cookie 过期时,触发扫码登录流程
|
2. `test_cookie_expired_triggers_login`: Cookie 过期时,触发扫码登录流程
|
||||||
3. 触发登录后重试成功
|
3. `test_login_retry_success`: 触发登录后重试成功
|
||||||
|
4. `test_login_failure_raises_error`: mock _trigger_qrcode_login 返回登录失败
|
||||||
|
|
||||||
需要 mock:
|
需要 mock:
|
||||||
login_result = ZhihuLoginResult(success=True, cookie_str="new_cookie")
|
- ZhihuCrawler.crawl_answer / crawl_article 返回 mock CrawlResult
|
||||||
- mock _trigger_qrcode_login 返回登录失败
|
- ZhihuLogin.validate_cookie 返回过期状态
|
||||||
- mock _trigger_qrcode_login 抛出异常
|
- ZhihuLogin.login_by_qrcode 返回登录结果
|
||||||
测试验证正确处理各种情况
|
</action>
|
||||||
</action>
|
|
||||||
<verify>
|
<verify>
|
||||||
<automated>pytest tests/test_platforms/test_zhihu.py -k "test_cookie" -v</automated>
|
<automated>pytest tests/test_platforms/test_zhihu.py -k "test_cookie" -v</automated>
|
||||||
</verify>
|
</verify>
|
||||||
<done>
|
<done>
|
||||||
Cookie 过期自动触发扫码登录的测试用例全部通过
|
Cookie 过期自动触发扫码登录的测试用例全部通过
|
||||||
</done>
|
</done>
|
||||||
</task>
|
</task>
|
||||||
|
|
||||||
<task type="auto">
|
<task type="auto" tdd="true">
|
||||||
<name>Task 3: Add comment formatting tests</name>
|
<name>Task 3: Verify comment formatting and idempotency</name>
|
||||||
<files>tests/test_platforms/test_zhihu.py</files>
|
<files>tests/test_platforms/test_zhihu.py</files>
|
||||||
|
<behavior>
|
||||||
|
- Test 1: 有评论时,格式化为 "## 热门评论" 部分
|
||||||
|
- Test 2: 无评论时,不追加评论部分
|
||||||
|
- Test 3: 幂等检查阻止重复处理同一内容
|
||||||
|
- Test 4: 不同内容 ID 可以独立处理
|
||||||
|
</behavior>
|
||||||
<action>
|
<action>
|
||||||
添加测试用例验证评论格式化:
|
移除 Wave 0 创建的测试骨架中的 pytest.mark.skip 标记,实现以下测试场景:
|
||||||
测试场景:
|
|
||||||
1. 有评论时,格式化为 "热门评论" 部分
|
1. `test_comment_formatting_with_comments`: 有评论时,格式化为 "## 热门评论" 部分
|
||||||
2. 无评论时,返回空字符串
|
2. `test_comment_formatting_no_comments`: 无评论时,不追加评论部分
|
||||||
使用 mock 数据验证格式正确
|
3. `test_idempotent_execution_skips_processed`: 幂等检查阻止重复处理同一内容
|
||||||
</action>
|
4. `test_different_content_processes_independently`: 不同内容 ID 可以独立处理
|
||||||
|
|
||||||
|
验证评论格式:
|
||||||
|
```markdown
|
||||||
|
[原回答/文章内容]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 热门评论
|
||||||
|
|
||||||
|
1. **@用户A**: 评论内容...
|
||||||
|
2. **@用户B**: 评论内容...
|
||||||
|
```
|
||||||
|
|
||||||
|
验证幂等性:
|
||||||
|
- 首次调用 fetch_metadata 应正常处理
|
||||||
|
- 再次调用相同 content_id 应跳过或返回缓存
|
||||||
|
</action>
|
||||||
<verify>
|
<verify>
|
||||||
<automated>pytest tests/test_platforms/test_zhihu.py -k "test_comment" -v</automated>
|
<automated>pytest tests/test_platforms/test_zhihu.py -k "test_comment or test_idempotent" -v</automated>
|
||||||
</verify>
|
</verify>
|
||||||
<done>
|
<done>
|
||||||
评论格式化测试用例全部通过
|
评论格式化测试用例全部通过
|
||||||
</done>
|
幂等执行测试用例全部通过
|
||||||
|
</done>
|
||||||
</task>
|
</task>
|
||||||
|
|
||||||
</tasks>
|
</tasks>
|
||||||
|
|
||||||
<verification>
|
<verification>
|
||||||
运行完整的 Pipeline 测试验证整合是否正常工作:
|
运行完整的 Pipeline 测试验证整合是否正常工作:
|
||||||
|
```bash
|
||||||
|
pytest tests/test_platforms/test_zhihu.py -v
|
||||||
|
```
|
||||||
</verification>
|
</verification>
|
||||||
|
|
||||||
<success_criteria>
|
<success_criteria>
|
||||||
- 知乎链接使用新爬虫处理器,无需手动设置 Cookie
|
- 知乎链接使用新爬虫处理器,无需手动设置 Cookie
|
||||||
- 新处理器与现有 Pipeline 架构完全兼容
|
- 新处理器与现有 Pipeline 架构完全兼容
|
||||||
- 支持断点续传和幂等执行(与其他处理器行为一致)
|
- 支持断点续传和幂等执行(通过 IdempotencyChecker 实现)
|
||||||
|
- 评论爬取默认开启(include_comments=True)
|
||||||
|
- 评论追加到正文末尾(格式: "---\n## 热门评论")
|
||||||
</success_criteria>
|
</success_criteria>
|
||||||
|
|
||||||
<output>
|
<output>
|
||||||
|
|||||||
Reference in New Issue
Block a user