mcpField
P
pricing-finder

pricing-finder

github.com/varnan-tech营销与增长68744 次安装2 周前更新
代码仓库

关于 pricing-finder

pricing-finder 是面向创始人和产品团队的定价研究技能,通过收集竞品定价信息进行比较分析。价格与建议以抓取页面或搜索摘要为依据,避免凭空估算。

主要功能

  1. 01寻找 5 个可比竞品
  2. 02抓取竞品定价页面
  3. 03比较模式、价格和功能门槛
  4. 04绘制定价定位图
  5. 05依据基准数据提出建议
  6. 06将定价信息关联至来源

适用场景

  1. 01制定产品价格前进行基准比较
  2. 02比较竞品套餐与功能限制
  3. 03准备有来源依据的定价评审

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/varnan-tech/opendirectory --skill pricing-finder

安装后在 Claude Code 中输入/pricing-finder确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

.env.example
README.md
requirements.txt
evals/
evals.json
references/
extraction-guide.md
positioning-guide.md
pricing-models.md
scripts/
research.py

详细介绍

定价查找器

告诉它你的产品 URL 或描述。它会查找 5 个竞争对手,获取他们的实际定价页面,并返回一份完整的定价情报报告:你所在领域的主流定价模式、基准价格表、功能门槛分析、定位图,以及针对你产品的具体定价建议。

无需任何必需的 API 密钥。 完全使用免费的 pip 依赖项运行。可选的 API 密钥有助于提升质量。


零幻觉政策: 输出中的每个价格、套餐名称和功能门槛都必须能追溯到已获取的定价页面内容或 DuckDuckGo 搜索摘要。具体要求:

  • 竞争对手价格:只能从已获取的页面内容中原样提取
  • “Contact Sales”:原样记录,不得估算或替换为数字
  • 套餐名称:从页面中准确复制,不得改写
  • 功能列表:从页面内容中提取,不得根据产品知识推断
  • 定位观察:只能根据基准价格表中的数据得出

常见错误

Agent 会想要……这样做为什么不对
把“Contact Sales”填成估算价格切勿估算企业定价。必须准确记录为“Contact Sales”。
使用训练知识获取竞争对手价格每个价格都必须能追溯到已获取的页面内容或搜索摘要。
跳过竞争对手确认步骤务必展示找到的竞争对手并等待确认。竞争对手选错,基准数据就会错。
不参考基准数据就给出价格建议每条价格建议都必须引用基准价格表中的具体数字。
当页面内容少于 500 个字符时,将页面标记为高质量少于 500 个字符意味着页面未能获取——将 data_quality 标记为 'low',并使用搜索摘要作为回退。
在输出中使用 em dash将所有 em dash 替换为连字符。

每次运行前阅读参考文件

cat references/pricing-models.md
cat references/extraction-guide.md
cat references/positioning-guide.md

步骤 1:检查环境

echo "TAVILY_API_KEY:    ${TAVILY_API_KEY:+set (search quality enhanced)}${TAVILY_API_KEY:-not set, DuckDuckGo will be used (free)}"
echo "FIRECRAWL_API_KEY: ${FIRECRAWL_API_KEY:+set (JS rendering enhanced)}${FIRECRAWL_API_KEY:-not set, requests+BS4 will be used (free)}"
echo ""
python3 -c "from ddgs import DDGS; import requests, bs4, html2text; print('Dependencies OK')" 2>/dev/null \
  || echo "ERROR: Missing dependencies. Run: pip install ddgs requests beautifulsoup4 html2text"

如果缺少依赖项: 立即停止。告知用户:“缺少 Python 依赖项。运行以下命令进行安装:pip install ddgs requests beautifulsoup4 html2text——全部免费,无需注册账号。然后重试。”

如果仅缺少 API 密钥: 继续。DuckDuckGo 和 requests+BS4 是默认的免费选项。

生成产品 slug:

PRODUCT_SLUG=$(python3 -c "
from urllib.parse import urlparse
import sys, re
url = 'URL_HERE'
if url.startswith('http'):
    host = urlparse(url).netloc.replace('www.', '')
    print(host.split('.')[0])
else:
    print(re.sub(r'[^a-z0-9]', '-', url[:30].lower()).strip('-'))
")
echo "Product slug: $PRODUCT_SLUG"

步骤 2:解析输入

从对话中收集:

  • product_url:要获取的 URL(必需,除非用户直接粘贴描述)
  • geography:可选——美国 / 欧洲 / 印度 / 全球。默认值:美国

如果用户只提供了粘贴的描述(没有 URL): 跳过步骤 3 和步骤 4。直接进入步骤 4(产品分析),并将粘贴的文本用作 product_content。将 page_source 设为 user_description,并在 data_quality_flags 中注明。

如果既没有 URL,也没有描述: 询问:“你的产品或初创公司的 URL 是什么?或者粘贴一段简短描述:它的功能、目标用户,以及它的差异化之处。”


步骤 3:获取产品页面

主要方式:Firecrawl(如果已设置 FIRECRAWL_API_KEY)

curl -s -X POST https://api.firecrawl.dev/v1/scrape \
  -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "URL_HERE", "formats": ["markdown"], "onlyMainContent": true}' \
  | python3 -c "
import sys, json
d = json.load(sys.stdin)
content = d.get('data', {}).get('markdown', '') or d.get('markdown', '')
print(f'Fetched via Firecrawl: {len(content)} characters')
open('/tmp/pf-product-raw.md', 'w').write(content)
"

备用方式:requests + BS4(免费,始终可用)

python3 << 'PYEOF'
import requests, html2text, random

USER_AGENTS = [
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
]
headers = {"User-Agent": random.choice(USER_AGENTS), "Accept": "text/html,application/xhtml+xml;q=0.9,*/*;q=0.8"}
resp = requests.get("URL_HERE", headers=headers, timeout=20, allow_redirects=True)
converter = html2text.HTML2Text()
converter.ignore_images = True
converter.body_width = 0
content = converter.handle(resp.text)[:8000]
print(f'Fetched via requests+BS4: {len(content)} characters')
open('/tmp/pf-product-raw.md', 'w').write(content)
PYEOF

检查点:

python3 -c "
content = open('/tmp/pf-product-raw.md').read()
if len(content) < 200:
    print('ERROR: fewer than 200 characters fetched -- page may be JS-rendered')
else:
    print(f'Content OK: {len(content)} characters')
"

如果内容少于 200 个字符: 告知用户:“产品页面返回的内容太少——网站可能使用了 JavaScript 渲染。请粘贴一段简短描述:你的产品有什么功能、目标用户是谁,以及它与竞争对手有何不同。”


第 4 步:产品分析(AI)

打印页面内容:

python3 -c "
content = open('/tmp/pf-product-raw.md').read()[:5000]
print('=== PRODUCT PAGE (first 5000 chars) ===')
print(content)
"

AI 指令: 分析上方的产品页面并提取:

  • product_name:产品或公司名称
  • one_line_description:产品的功能、目标用户和核心价值主张。少于 20 个词。不要使用营销语言。
  • industry_taxonomy:l1(顶级类别:开发者工具 / 金融科技 / 医疗科技 / 消费品等)、l2(领域:DevOps / 支付 / 人力资源等)、l3(细分领域:CI/CD 自动化 / 嵌入式支付 / 异步视频等)
  • differentiators:恰好 2-3 项能体现该产品差异化的具体特点。这些内容将用于推荐,因此请务必具体。诸如“易于使用”这样的笼统回答不可接受。
  • icp:buyer_persona(职位)、company_type、company_size
  • geography_bias:美国 / 欧洲 / 印度 / 全球
  • page_source:"live_page" 或 "user_description"

写入 /tmp/pf-product-analysis.json:

python3 << 'PYEOF'
import json

analysis = {
    # FILL from your analysis above
    "product_name": "",
    "one_line_description": "",
    "industry_taxonomy": {"l1": "", "l2": "", "l3": ""},
    "differentiators": [],
    "icp": {"buyer_persona": "", "company_type": "", "company_size": ""},
    "geography_bias": "US",
    "page_source": "live_page"
}

json.dump(analysis, open('/tmp/pf-product-analysis.json', 'w'), indent=2)
print('Product analysis written.')
PYEOF

验证:

python3 -c "
import json
a = json.load(open('/tmp/pf-product-analysis.json'))
print('Product:', a['product_name'])
print('Industry:', a['industry_taxonomy']['l1'], '>', a['industry_taxonomy']['l2'], '>', a['industry_taxonomy']['l3'])
print('Differentiators:')
for d in a['differentiators']:
    print(f'  - {d}')
"

第 4b 步:阶段 1——发现竞争对手

ls scripts/research.py 2>/dev/null && echo "script found" || echo "ERROR: scripts/research.py not found -- cannot continue"
python3 scripts/research.py \
  --phase discover \
  --product-analysis /tmp/pf-product-analysis.json \
  --output /tmp/pf-competitors-raw.json

打印结果以供 AI 审核:

python3 -c "
import json
data = json.load(open('/tmp/pf-competitors-raw.json'))
print(f'Searches run: {len(data[\"competitor_searches\"])}')
for s in data['competitor_searches']:
    print(f'\nQuery: {s[\"query\"]}')
    for r in s.get('results', [])[:6]:
        print(f'  - {r[\"title\"]} | {r[\"url\"]}')
        print(f'    {r.get(\"snippet\",\"\")[:150]}')
"

AI 指令: 阅读上方的搜索结果。准确选择 5 家竞争公司,要求:

  1. 在搜索结果标题或摘要中提到
  2. 与所分析产品属于同一 L3 细分领域
  3. 是真正的软件产品(不是代理机构、列表文章或评测网站)
  4. 彼此各不相同

为每家竞争公司填写:name、url、pricing_url(其定价页面;若摘要中未找到,则推断为 [url]/pricing)、description(根据摘要写一句话描述)、source_url。


第 5 步:确认竞争对手

python3 << 'PYEOF'
import json

analysis = json.load(open('/tmp/pf-product-analysis.json'))

# FILL: 5 competitors from the search results above
candidates = [
    # {"name": str, "url": str, "pricing_url": str, "description": str, "source_url": str}
]

print(f"\nFound 5 competitors for {analysis['product_name']} in {analysis['industry_taxonomy']['l3']}:\n")
for i, c in enumerate(candidates, 1):
    print(f"  {i}. {c['name']} -- {c['description']}")
    print(f"     Product: {c['url']}")
    print(f"     Pricing: {c['pricing_url']}")

data = json.load(open('/tmp/pf-competitors-raw.json'))
data['competitor_candidates'] = candidates
json.dump(data, open('/tmp/pf-competitors-raw.json', 'w'), indent=2)
PYEOF

告诉用户:“以下是我将抓取定价数据的 5 家竞争公司。你可以添加、移除或替换任意公司,也可以说‘看起来不错’继续。”

等待确认。 如果用户编辑列表,请相应更新候选项。然后写入确认后的列表:

python3 << 'PYEOF'
import json

# FILL: confirmed competitor list (after user review)
confirmed = [
    # {"name": str, "url": str, "pricing_url": str}
]

json.dump({"confirmed_competitors": confirmed}, open('/tmp/pf-competitors-confirmed.json', 'w'), indent=2)
print(f"Confirmed {len(confirmed)} competitors for pricing research.")
for c in confirmed:
    print(f"  - {c['name']} | pricing: {c['pricing_url']}")
PYEOF

第 6 步:阶段 2——抓取定价页面

python3 scripts/research.py \
  --phase fetch-pricing \
  --competitors /tmp/pf-competitors-confirmed.json \
  --output /tmp/pf-pricing-raw.json

此步骤使用 3 层回退机制抓取每家竞争公司的定价页面:

  1. 直接抓取:requests + beautifulsoup4 + html2text
  2. Google 缓存:webcache.googleusercontent.com/search?q=cache:[url]
  3. DuckDuckGo 搜索:"[competitor]" pricing plans cost per month(摘要回退)

打印抓取摘要:

python3 -c "
import json
data = json.load(open('/tmp/pf-pricing-raw.json'))
print(f'Competitors fetched: {data[\"competitors_fetched\"]}')
print()
for r in data['results']:
    quality_label = {'high': 'GOOD', 'medium': 'OK', 'low': 'SNIPPET ONLY'}.get(r['data_quality'], r['data_quality'])
    print(f'  {r[\"name\"]:20} {r[\"source\"]:15} {r[\"content_length\"]:5} chars  [{quality_label}]')
"

如果竞争公司的 data_quality: low: 这表示定价页面被屏蔽或由 JS 渲染。分析将使用搜索摘要继续进行,但会将该竞争公司的置信度标记为低。


第 7 步:提取定价信息(AI)

打印所有原始定价内容:

python3 -c "
import json
data = json.load(open('/tmp/pf-pricing-raw.json'))
for r in data['results']:
    print(f'\n=== {r[\"name\"]} (source: {r[\"source\"]}, quality: {r[\"data_quality\"]}) ===')
    print(f'Pricing URL: {r[\"pricing_url\"]}')
    print(r['content'][:4000])
    print('---')
"

AI 指令: 根据上方内容,为每家竞争公司提取结构化定价数据。请遵循 references/extraction-guide.md,了解如何识别套餐、价格、限制和 CTA。

零幻觉规则:

  1. 仅从内容中逐字提取价格。如果内容中没有价格,则填写 null。
  2. 按原样记录 “Contact Sales”。绝不要替换为估算数字。
  3. data_quality: low 表示数据来自搜索摘要——提取其中已有信息,但不得根据训练知识补全缺失内容。
  4. 对于内容中没有的字段:填写 "not found in page data"。
  5. 年付价格:始终同时记录月均价格和年付总额。

写入 /tmp/pf-pricing-extracted.json:

python3 << 'PYEOF'
import json

# FILL: one object per competitor, following the schema below
extracted = [
    # {
    #   "competitor": str,
    #   "pricing_url": str,
    #   "data_quality": "high" | "medium" | "low",
    #   "pricing_model": "per-seat" | "flat-rate" | "usage-based" | "freemium" | "tiered-flat" | "hybrid",
    #   "billing_cadence": ["monthly"] | ["annual"] | ["monthly", "annual"],
    #   "annual_discount": str,           # e.g. "20%" or "not found in page data"
    #   "free_tier": true | false,
    #   "free_trial": true | false,
    #   "free_trial_days": int | null,
    #   "tiers": [
    #     {
    #       "name": str,
    #       "price_monthly": float | null,       # null if Contact Sales
    #       "price_annual_monthly": float | null, # per-month equivalent when billed annually
    #       "price_note": str,                   # "Contact Sales", "Free", or empty
    #       "seats": str,                        # "per seat", "unlimited", "up to 5", etc.
    #       "key_limits": [str],                 # storage, API calls, projects, etc.
    #       "key_features": [str]                # top 3-5 features in this tier
    #     }
    #   ],
    #   "enterprise_tier": true | false,
    #   "enterprise_pricing": str,               # "Contact Sales" or actual price
    #   "regional_pricing": str | null           # e.g. "India: ₹999/mo" or null
    # }
]

json.dump(extracted, open('/tmp/pf-pricing-extracted.json', 'w'), indent=2)
print(f'Extracted pricing for {len(extracted)} competitors.')
for c in extracted:
    tier_count = len(c.get('tiers', []))
    print(f"  {c['competitor']:20} model={c['pricing_model']:15} tiers={tier_count} quality={c['data_quality']}")
PYEOF

第 8 步:模式分析(AI)

打印所有提取的定价数据:

python3 -c "
import json
data = json.load(open('/tmp/pf-pricing-extracted.json'))
for c in data:
    print(f'\n{c[\"competitor\"]} ({c[\"pricing_model\"]}, quality={c[\"data_quality\"]})')
    for t in c.get('tiers', []):
        price = t.get('price_monthly')
        label = t.get('price_note', '')
        print(f'  {t[\"name\"]:15} \${price}/mo' if price is not None else f'  {t[\"name\"]:15} {label}')
"

AI 指令: 分析所有提取的定价数据并归纳模式。请遵循 references/positioning-guide.md 进行定位分析。

写入 /tmp/pf-patterns.json:

python3 << 'PYEOF'
import json

patterns = {
    # FILL from analysis

    # Dominant model across 5 competitors
    "dominant_model": "",                         # the most common model
    "model_breakdown": {},                        # {"per-seat": 3, "flat-rate": 1, "freemium": 1}
    "model_explanation": "",                      # 2 sentences: why this model dominates this space

    # Price benchmarks (USD/mo, monthly billing)
    "entry_tier": {
        "min": None, "max": None, "median": None,
        "currency": "USD/mo",
        "note": ""                                # e.g. "based on 4/5 competitors (1 was search snippet only)"
    },
    "mid_tier": {
        "min": None, "max": None, "median": None,
        "currency": "USD/mo",
        "note": ""
    },
    "enterprise_floor": "",                       # e.g. "$99+/mo" or "Contact Sales (4/5 competitors)"

    # Billing patterns
    "annual_discount_typical": "",                # e.g. "15-20%"
    "billing_cadence_dominant": "",               # "monthly + annual", "monthly only", "annual only"

    # Free tier / trial prevalence
    "free_tier_count": 0,                         # how many of 5 offer free tier
    "free_trial_count": 0,                        # how many of 5 offer free trial
    "free_tier_typical_limits": [],               # what's typically in a free tier

    # Feature gates
    "always_free_features": [],                   # features present in all free/entry tiers
    "always_paid_features": [],                   # features locked behind paid in all competitors
    "variable_features": [],                      # features that vary most across competitors

    # Regional pricing
    "regional_pricing_flags": [],                 # competitors with region-specific pricing

    # Data quality
    "high_quality_count": 0,                      # competitors with fetched page data
    "low_quality_count": 0,                       # competitors with snippet-only data
    "data_quality_flags": []
}

json.dump(patterns, open('/tmp/pf-patterns.json', 'w'), indent=2)
print('Patterns written.')
print(f"Dominant model: {patterns['dominant_model']}")
print(f"Entry tier: ${patterns['entry_tier']['min']}-${patterns['entry_tier']['max']}/mo (median ${patterns['entry_tier']['median']})")
print(f"Free tier: {patterns['free_tier_count']}/5 | Free trial: {patterns['free_trial_count']}/5")
PYEOF

步骤 9:定位图 + 推荐(AI)

打印汇总数据:

python3 -c "
import json

analysis  = json.load(open('/tmp/pf-product-analysis.json'))
extracted = json.load(open('/tmp/pf-pricing-extracted.json'))
patterns  = json.load(open('/tmp/pf-patterns.json'))

print('=== PRODUCT ===')
print(f'Name: {analysis[\"product_name\"]}')
print(f'What it does: {analysis[\"one_line_description\"]}')
print('Differentiators:')
for d in analysis['differentiators']:
    print(f'  - {d}')

print()
print('=== PATTERNS ===')
print(f'Dominant model: {patterns[\"dominant_model\"]}  breakdown: {patterns[\"model_breakdown\"]}')
print(f'Entry tier: \${patterns[\"entry_tier\"][\"min\"]}-\${patterns[\"entry_tier\"][\"max\"]}/mo (median \${patterns[\"entry_tier\"][\"median\"]})')
print(f'Mid tier:   \${patterns[\"mid_tier\"][\"min\"]}-\${patterns[\"mid_tier\"][\"max\"]}/mo (median \${patterns[\"mid_tier\"][\"median\"]})')
print(f'Enterprise: {patterns[\"enterprise_floor\"]}')
print(f'Free tier: {patterns[\"free_tier_count\"]}/5 | Free trial: {patterns[\"free_trial_count\"]}/5')

print()
print('=== COMPETITOR PRICING SUMMARY ===')
for c in extracted:
    print(f'{c[\"competitor\"]} ({c[\"pricing_model\"]}):')
    for t in c.get('tiers', []):
        p = t.get('price_monthly')
        print(f'  {t[\"name\"]}: \${p}/mo' if p is not None else f'  {t[\"name\"]}: {t.get(\"price_note\",\"\")}')
"

AI 指令 -- 零幻觉规则:

  1. 定位图: 从提取的数据中点名具体竞品。不得虚构观察结果。
  2. 未满足的需求缺口: 必须提及数据中缺失的具体价格区间或模型类型。
  3. 每项价格建议: 必须引用 patterns JSON 中的具体数字(entry_tier.median、mid_tier.median 等)。
  4. 免费套餐建议: 必须引用 patterns 中的 free_tier_count(例如:“5 家竞品中有 3 家提供免费套餐,因此不提供免费套餐存在风险”)。
  5. 差异化优势门槛: 从分析中的产品 differentiators 列表中选择,不得虚构功能。
  6. 不得使用长破折号。不得使用禁用词(powerful、seamless、game-changing、revolutionary、cutting-edge、leverage)。

生成:

  1. 定位图:哪些产品占据各个象限(便宜+简单、中端、企业级),以及未满足的需求缺口
  2. 推荐定价策略:模式 + 所有套餐价格 + 免费套餐决策 + 年度折扣 + 需要设置限制的内容

写入 /tmp/pf-final.json:

python3 << 'PYEOF'
import json

result = {
    "product_summary": {
        # FILL from analysis
        "product_name": "",
        "one_line_description": "",
        "differentiators": []
    },
    "competitors_researched": [],  # FILL: list of competitor names

    # Filled from patterns
    "pricing_model_analysis": {
        "dominant_model": "",
        "model_breakdown": {},
        "model_explanation": "",
        "free_tier_count": 0,
        "free_trial_count": 0,
        "annual_discount_typical": ""
    },

    # Benchmark table (filled from extracted data)
    "benchmark_table": [
        # Per competitor:
        # {"name": str, "model": str, "entry_price": str, "mid_price": str,
        #  "top_price": str, "free_tier": bool, "free_trial": bool, "data_quality": str}
    ],

    # Market ranges
    "market_ranges": {
        "entry": {"min": None, "max": None, "median": None},
        "mid":   {"min": None, "max": None, "median": None},
        "enterprise": ""
    },

    # Feature gate analysis
    "feature_gates": {
        "always_free": [],
        "always_paid": [],
        "most_variable": []
    },

    # Positioning map
    "positioning_map": {
        "cheap_simple": {"competitor": "", "price": ""},
        "middle_market": [],
        "enterprise": {"competitor": "", "note": ""},
        "underserved_gap": ""
    },

    # Recommendation
    "recommendation": {
        "model": "",
        "model_justification": "",       # references specific data from model_breakdown
        "entry_price": "",               # e.g. "$12/mo"
        "entry_justification": "",       # references entry_tier.median
        "mid_price": "",
        "mid_justification": "",
        "top_price": "",                 # price or "Contact Sales"
        "top_justification": "",
        "free_tier": True,               # bool
        "free_tier_justification": "",   # references free_tier_count
        "annual_discount": "",           # e.g. "17%"
        "annual_justification": "",
        "gate_behind_paid": "",          # specific differentiator from product analysis
        "gate_justification": ""
    },

    "data_quality_flags": []
}

json.dump(result, open('/tmp/pf-final.json', 'w'), indent=2)
print('Synthesis written.')
print(f'Benchmark table: {len(result.get("benchmark_table", []))} competitors')
print(f'Recommendation model: {result.get("recommendation", {}).get("model", "--")}')
PYEOF

步骤 10:自我质检、展示并保存

自我质检:

python3 << 'PYEOF'
import json

result = json.load(open('/tmp/pf-final.json'))
failures = []

# Check 1: em dashes
full_text = json.dumps(result)
if '—' in full_text:
    result = json.loads(full_text.replace('—', '-'))
    failures.append('Fixed: em dashes replaced with hyphens')

# Check 2: banned words
banned = ['powerful', 'seamless', 'innovative', 'game-changing', 'revolutionize',
          'cutting-edge', 'best-in-class', 'world-class', 'leverage', 'disrupt', 'transform']
for word in banned:
    if word.lower() in json.dumps(result).lower():
        failures.append(f'Warning: banned word "{word}" found in output')

# Check 3: recommendation completeness
rec = result.get('recommendation', {})
required = ['model', 'entry_price', 'mid_price', 'top_price', 'free_tier',
            'entry_justification', 'mid_justification', 'gate_behind_paid']
for field in required:
    if not rec.get(field) and rec.get(field) is not False:
        failures.append(f'Warning: recommendation missing field: {field}')

# Check 4: no Contact Sales replaced with numbers
for row in result.get('benchmark_table', []):
    for field in ['entry_price', 'mid_price', 'top_price']:
        val = str(row.get(field, ''))
        if 'contact' in val.lower():
            pass  # correct
        elif row.get('data_quality') == 'low' and '$' in val:
            failures.append(f'Warning: {row["name"]} has dollar prices from low-quality source')

# Check 5: benchmark table populated
if len(result.get('benchmark_table', [])) < 3:
    failures.append(f'Warning: benchmark table has only {len(result.get("benchmark_table", []))} competitors -- need at least 3 for reliable benchmarks')

# Check 6: "not found in page data" count
nf = json.dumps(result).count('not found in page data')
if nf > 0:
    failures.append(f'INFO: {nf} field(s) marked "not found in page data"')

if 'data_quality_flags' not in result:
    result['data_quality_flags'] = []
result['data_quality_flags'].extend(failures)

json.dump(result, open('/tmp/pf-final.json', 'w'), indent=2)
print(f'QA complete. {len(failures)} issues.')
for f in failures:
    print(f'  - {f}')
if not failures:
    print('All QA checks passed.')
PYEOF

展示输出:

## Pricing Intel: [product_name]
Date: [today] | Competitors: [list] | Geography: [geography]

---

### Your Product
[one_line_description]
Differentiators: [list]

---

### 1. Pricing Model Analysis
Dominant model: [dominant_model] ([N]/5 competitors)
[model_explanation -- 2-3 sentences on why this model dominates the space]

Free tier: [N]/5 competitors | Free trial: [N]/5 | Annual discount: typical [X]%

---

### 2. Price Point Benchmark Table
| Competitor | Model | Entry | Mid | Top | Free tier | Free trial | Data quality |
|---|---|---|---|---|---|---|---|
[one row per competitor from benchmark_table]

Market ranges:
- Entry tier: $[min]-$[max]/mo (median $[median])
- Mid tier:   $[min]-$[max]/mo (median $[median])
- Enterprise: [enterprise_floor]

---

### 3. Feature Gate Analysis
Always free: [always_free list]
Always behind paid: [always_paid list]
Most variable across competitors: [most_variable list]

---

### 4. Competitive Positioning Map
Cheap + simple: [competitor] at $[X]/mo
Middle market:  [competitors] at $[X]-$[Y]/mo
Enterprise:     [competitor] (Contact Sales)
Underserved gap: [underserved_gap -- specific observation]

---

### 5. Recommended Pricing for [product_name]
Model: [model] -- [model_justification]
Entry: [entry_price] -- [entry_justification]
Mid:   [mid_price] -- [mid_justification]
Top:   [top_price] -- [top_justification]
Free tier: [Yes/No] -- [free_tier_justification]
Annual discount: [annual_discount] -- [annual_justification]
Gate behind paid: [gate_behind_paid] -- [gate_justification]

---
Data notes: [data_quality_flags or "None"]
Saved to: docs/pricing-intel/[PRODUCT_SLUG]-[DATE].md

保存到文件并清理:

DATE=$(date +%Y-%m-%d)
OUTPUT_FILE="docs/pricing-intel/${PRODUCT_SLUG}-${DATE}.md"
mkdir -p docs/pricing-intel
echo "Saved to: $OUTPUT_FILE"
rm -f /tmp/pf-product-raw.md /tmp/pf-product-analysis.json \
      /tmp/pf-competitors-raw.json /tmp/pf-competitors-confirmed.json \
      /tmp/pf-pricing-raw.json /tmp/pf-pricing-extracted.json \
      /tmp/pf-patterns.json /tmp/pf-final.json
echo "Temp files cleaned up."

评论

支持 Markdown