ワンクリックで
tdd-workflow
Amazon 商品 HTML 提取器的 TDD 工作流。先写测试后写代码,9 步执行顺序(每步带 CHECKPOINT),Smoke Fixture 选取策略,测试代码风格模板。当 agent 需要按 TDD 流程开发提取器时调度此技能。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Amazon 商品 HTML 提取器的 TDD 工作流。先写测试后写代码,9 步执行顺序(每步带 CHECKPOINT),Smoke Fixture 选取策略,测试代码风格模板。当 agent 需要按 TDD 流程开发提取器时调度此技能。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
当需要分析 Amazon Bestsellers Top50 的 A+ 页面内容、视觉营销策略、品牌故事、产品对比表、图片素材质量时触发此 skill。 包括但不限于:A+ 模块结构分析、图片视觉风格对比、Comparison Table 分析、品牌叙事策略、A+ 文本内容提取等。 示例触发语:「分析 A+ 页面」「哪些产品的 A+ 做得好」「A+ 图片风格对比」「Comparison Table 怎么设计的」「A+ 文案分析」
当需要对 Amazon Bestsellers Top50 做逐商品更细分类分析时触发此 skill。 适用于平台类目过粗而业务需要细粒度标签的场景。该技能基于 PPD + Product Details + 商品图证据, 输出全量 Top50 的细分类明细表、分布统计和机会判断,且支持全类目通用。
当需要分析 Amazon Bestsellers Top50 的市场竞争格局、排名坑位结构、品牌集中度、价格带分布、卖家结构时触发此 skill。 包括但不限于:类目概览骨架判断、坑位门槛分析、品牌/卖家占坑、新卖家进入路径、市场体量代理判断、自营占比等。 示例触发语:「分析这个类目的市场竞争格局」「排名前10被谁占了」「新卖家有没有机会进入」「品牌集中度怎么样」「价格带分布如何」
当需要分析 Amazon Bestsellers Top50 的用户评论结构、购买动机、高频痛点、产品实用性判断时触发此 skill。 包括但不限于:评论层级分布、用户核心购买理由、差评痛点提炼、产品切入机会识别等。 示例触发语:「分析用户评论」「用户最在意什么」「差评集中在哪里」「产品体验痛点是什么」「新品应该改进什么」
Amazon 商品完整 HTML 页面的分块器。读取 ≈2MB 的完整详情页 HTML,按稳定 DOM id 切出 4 个子 HTML(ppd / customer_reviews / product_details / aplus)。当 agent 需要对完整 HTML 进行分块切分时调度此技能。
Amazon 商品子 HTML 块的结构化提取器(清洗器)。读取分块后的子 HTML,清洗 DOM 噪声,输出结构化 Markdown。包含 4 个子技能(ppd / customer-reviews / aplus / product-details),每个负责一种块类型。当 agent 需要从子 HTML 中提取结构化数据时调度此技能。
SOC 職業分類に基づく
| name | tdd-workflow |
| description | Amazon 商品 HTML 提取器的 TDD 工作流。先写测试后写代码,9 步执行顺序(每步带 CHECKPOINT),Smoke Fixture 选取策略,测试代码风格模板。当 agent 需要按 TDD 流程开发提取器时调度此技能。 |
| type | skill |
<script>, <br>, 导航文本等)test_*_golden_comparison 用例(详见 skills/golden-fixture/SKILL.md)每个步骤必须 实际运行 pytest 并确认通过后才能进入下一步。
1. Smoke Fixture 选取:
a. 从 `products/{ASIN}/product.html` 中手动指定 3–4 个代表性 ASIN(优先 Top1/Top25)
b. 运行 `python -m chunker.batch_run --products-dir <products_dir> --rankings-jsonl <rankings_jsonl> --out-dir chunks/ --limit 4`
确认能正常分块生成 chunks
c. 这 3–4 个产品的 chunk 目录就是后续所有提取器测试的固定 fixture
2. DOM 探测:
读取上述 3–4 个样本 → 用 Python 脚本探测 DOM 结构(临时脚本,写到 tests/ 下,用完删除)
3. 分块器:
a. 写测试 tests/test_static_chunker.py
b. 实现 chunker/static_chunker.py
c. ✅ CHECKPOINT: `python -m pytest tests/test_static_chunker.py -v`
4. Reviews 提取器:
a. 复制 skills/amazon-extractor/skills/customer-reviews/customer_reviews_extract.py 到 chunker/customer_reviews_extract.py
b. 写测试 tests/test_customer_reviews_extract.py(结构断言 + Golden 比对)
c. ✅ CHECKPOINT: `python -m pytest tests/test_customer_reviews_extract.py -v`
d. 失败只微调模版,不得重写
5. Details 提取器:
a. 写测试 tests/test_product_details_extract.py(结构断言 + Golden 比对)
b. 实现 chunker/product_details_extract.py
c. ✅ CHECKPOINT: `python -m pytest tests/test_product_details_extract.py -v`
6. PPD 提取器:
a. 写测试 tests/test_ppd_extract.py(Core/Buybox/Twister/Overview/Bullets/Images + Golden 比对)
b. 逐子阶段实现
c. ✅ CHECKPOINT: `python -m pytest tests/test_ppd_extract.py -v`
7. A+ 提取器:
a. 写测试 tests/test_aplus_extract.py(Comparison/Assets/Story + 两个 Golden 比对)
b. 逐子阶段实现
c. ✅ CHECKPOINT: `python -m pytest tests/test_aplus_extract.py -v`
8. 编排脚本:
a. 写测试 tests/test_batch_run.py
b. 实现 chunker/batch_run.py
c. ✅ CHECKPOINT: `python -m pytest tests/test_batch_run.py -v`
9. ✅ FINAL GATE: `python -m pytest tests/ -v` 全部通过
# 文件位置:tests/test_ppd_extract.py
import tempfile
import unittest
from pathlib import Path
# Smoke Fixture:只针对 3–4 个样本,不面向全量数据
CHUNKS_DIR = Path(__file__).resolve().parents[1] / "chunks"
SMOKE_SAMPLE_COUNT = 4
SMOKE_DIRS = sorted(
[d for d in CHUNKS_DIR.iterdir() if d.is_dir() and (d / "ppd.html").exists()]
)[:SMOKE_SAMPLE_COUNT]
class TestPpdExtractor(unittest.TestCase):
def test_product_001_core_fields(self):
self.assertTrue(len(SMOKE_DIRS) >= 1, "No smoke fixture chunks found")
html_path = SMOKE_DIRS[0] / "ppd.html"
with tempfile.TemporaryDirectory() as tmp:
out = Path(tmp) / "ppd.md"
result = extract_ppd_markdown(html_path, out)
content = result.read_text(encoding="utf-8")
self.assertIn("# PPD Extracted", content)
self.assertIn("## Core", content)
self.assertIn("- Title:", content)
self.assertIn("- Current price: $", content)
if "| Field | Value |" in content:
self.assertIn("| --- | --- |", content)
self.assertNotIn("<br", content.lower())
self.assertNotIn("<script", content.lower())
def test_product_002_also_works(self):
if len(SMOKE_DIRS) < 2:
self.skipTest("Only 1 smoke fixture available")
html_path = SMOKE_DIRS[1] / "ppd.html"
with tempfile.TemporaryDirectory() as tmp:
out = Path(tmp) / "ppd.md"
result = extract_ppd_markdown(html_path, out)
content = result.read_text(encoding="utf-8")
self.assertIn("# PPD Extracted", content)
self.assertIn("## Core", content)
def test_golden_comparison(self):
"""Compare output against Golden fixture; retry 3x; escalate to human review if unstable."""
self.assertTrue(len(SMOKE_DIRS) >= 1, "No smoke fixture chunks found")
html_path = SMOKE_DIRS[0] / "ppd.html"
golden_path = TEMPLATES_DIR / "ppd_extracted.md"
if not html_path.exists():
self.skipTest("Reference sample chunk not found")
if not golden_path.exists():
self.skipTest("Golden fixture not found")
_run_with_golden_retry(self, extract_ppd_markdown, html_path, golden_path)
CHUNKS_DIR = Path(__file__).resolve().parents[1] / "chunks"sorted([d for d in CHUNKS_DIR.iterdir() if d.is_dir() and (d / "<block>.html").exists()])[:SMOKE_SAMPLE_COUNT]