Initial commit: Hermes Agent skills collection
- Trading skills (OKX, dividend, lottery, quantitative) - Creative skills (ASCII art, diagrams, video) - Development skills (GitHub, debugging, TDD) - Research skills (arXiv, blog monitoring) - Productivity skills (email, documents, notes) - MCP integration skills - Custom user skills
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
---
|
||||
name: pain-point-scraper
|
||||
description: 自动采集用户痛点/需求 - 从Reddit、Product Hunt、Hacker News等平台抓取用户评论,用LLM分析痛点、需求、机会。支持多来源聚合+结构化报告。当用户说"痛点分析"、"用户需求"、"市场调研"、"竞品分析"时触发。
|
||||
version: 1.0.0
|
||||
tags: [research, pain-point, user-research, market-analysis, scraping]
|
||||
triggers:
|
||||
- 痛点分析
|
||||
- 用户需求
|
||||
- 市场调研
|
||||
- 竞品分析
|
||||
- 用户痛点
|
||||
- pain point
|
||||
- user research
|
||||
---
|
||||
|
||||
# 用户痛点自动抓取与分析
|
||||
|
||||
从多个平台自动采集用户评论/反馈,用 LLM 提取痛点、需求、机会。
|
||||
|
||||
## 数据源
|
||||
|
||||
| 来源 | 采集方式 | 适用场景 |
|
||||
|------|----------|----------|
|
||||
| **Reddit** | JSON API (无需key) | 产品讨论、用户抱怨 |
|
||||
| **Hacker News** | Algolia API | 技术产品、开发者需求 |
|
||||
| **Product Hunt** | Web scraping | 新产品反馈 |
|
||||
| **Twitter/X** | Web search | 实时讨论 |
|
||||
| **应用商店** | Web scraping | App用户评价 |
|
||||
|
||||
## 使用方式
|
||||
|
||||
### 方式1:Agent 直接分析(推荐)
|
||||
|
||||
直接告诉 Agent 你想分析什么主题,Agent 会:
|
||||
1. 用 `web_search` 从 Reddit/HN/ProductHunt 采集数据
|
||||
2. 用 LLM 分析痛点
|
||||
3. 生成结构化报告
|
||||
|
||||
示例对话:
|
||||
```
|
||||
用户: 分析一下"AI写作工具"的用户痛点
|
||||
Agent: [自动采集+分析+生成报告]
|
||||
```
|
||||
|
||||
### 方式2:脚本采集 + Agent 分析
|
||||
|
||||
```bash
|
||||
cd ~/.hermes/skills/pain-point-scraper/scripts
|
||||
# 只采集原始数据
|
||||
python3 pain_point_scraper.py --topic "AI写作工具" --sources reddit,hn --limit 20 --raw --output data.json
|
||||
# 然后让 Agent 分析 data.json
|
||||
```
|
||||
|
||||
### 方式3:定时监控
|
||||
|
||||
创建 cron job,每天自动采集+分析+推送报告。
|
||||
|
||||
## 工作流(Agent执行)
|
||||
|
||||
当用户要求分析痛点时,Agent 应执行:
|
||||
|
||||
```
|
||||
1. web_search: 搜索 "site:reddit.com {topic} complaints/problems"
|
||||
2. web_search: 搜索 "site:news.ycombinator.com {topic}"
|
||||
3. web_search: 搜索 "site:producthunt.com {topic} reviews"
|
||||
4. 合并所有搜索结果
|
||||
5. LLM 分析:提取痛点、需求、机会
|
||||
6. 生成结构化报告(参考 references/example-report.md)
|
||||
```
|
||||
|
||||
## 输出格式
|
||||
|
||||
### 结构化痛点报告
|
||||
|
||||
```markdown
|
||||
# 🔍 痛点分析报告:{主题}
|
||||
> 数据来源:Reddit, HN | 采集时间:{datetime} | 分析评论数:{N}
|
||||
|
||||
## 📊 概览
|
||||
- 总评论数:N
|
||||
- 负面情绪占比:X%
|
||||
- 高频痛点:N个
|
||||
|
||||
## 🔥 TOP 痛点
|
||||
|
||||
### 1. {痛点标题} (提及次数: N)
|
||||
**用户原话**:
|
||||
> "{原文摘录}"
|
||||
|
||||
**痛点描述**:{LLM分析}
|
||||
**影响人群**:{目标用户}
|
||||
**现有解决方案**:{竞品/替代品}
|
||||
**机会评估**:⭐⭐⭐⭐ (4/5)
|
||||
|
||||
### 2. ...
|
||||
|
||||
## 💡 机会洞察
|
||||
- {基于痛点的产品/功能建议}
|
||||
- {未被满足的需求}
|
||||
|
||||
## 📈 趋势观察
|
||||
- {近期讨论趋势}
|
||||
```
|
||||
|
||||
## 脚本说明
|
||||
|
||||
- `scripts/pain_point_scraper.py` — 主脚本,采集+分析
|
||||
- `templates/report.html` — 可视化报告模板
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. Reddit/HN API 免费无需key,但有频率限制
|
||||
2. LLM分析需要能调用当前模型的API
|
||||
3. 建议每次分析不超过50条评论(避免token超限)
|
||||
@@ -0,0 +1,133 @@
|
||||
# 🔍 痛点分析报告:AI写作工具
|
||||
> 数据来源:Reddit, Hacker News, Product Hunt | 采集时间:2026-05-29 | 分析评论数:50+
|
||||
|
||||
---
|
||||
|
||||
## 📊 概览
|
||||
- 总评论数:50+
|
||||
- 主要痛点数:8个
|
||||
- 整体情绪:**负面偏多**(用户普遍不满现状)
|
||||
|
||||
---
|
||||
|
||||
## 🔥 TOP 痛点
|
||||
|
||||
### 1. 内容质量空洞 (提及次数: 高频)
|
||||
**用户原话**:
|
||||
> "输出内容空洞、重复、缺乏深度和原创性"
|
||||
> "千篇一律,缺乏个性化和创意"
|
||||
|
||||
**痛点描述**:AI生成的内容虽然语法正确,但缺乏灵魂、深度和真正有价值的洞察。用户需要花大量时间编辑。
|
||||
|
||||
**影响人群**:内容创作者、营销人员、博主
|
||||
|
||||
**现有解决方案**:Jasper、Copy.ai、Writesonic — 但都存在同样问题
|
||||
|
||||
**机会评估**:⭐⭐⭐⭐⭐ (5/5) — 这是最核心的痛点
|
||||
|
||||
---
|
||||
|
||||
### 2. 事实准确性差 (提及次数: 高频)
|
||||
**用户原话**:
|
||||
> "生成的内容可能包含错误信息或虚构事实"
|
||||
> "AI会一本正经地胡说八道"
|
||||
|
||||
**痛点描述**:AI经常"幻觉",编造不存在的数据、引用、事实,用户必须逐条核实。
|
||||
|
||||
**影响人群**:学术研究者、新闻工作者、专业内容创作者
|
||||
|
||||
**机会评估**:⭐⭐⭐⭐⭐ (5/5) — 准确性是信任的基础
|
||||
|
||||
---
|
||||
|
||||
### 3. 缺乏个性化/风格一致性 (提及次数: 中频)
|
||||
**用户原话**:
|
||||
> "难以保持一致风格,无法维持品牌声音"
|
||||
> "不能根据用户特定需求进行定制"
|
||||
|
||||
**痛点描述**:每个品牌/个人都有独特的写作风格,但AI无法学习和保持这种一致性。
|
||||
|
||||
**影响人群**:品牌营销团队、个人博主
|
||||
|
||||
**机会评估**:⭐⭐⭐⭐ (4/5) — 差异化竞争的关键
|
||||
|
||||
---
|
||||
|
||||
### 4. 价格与价值不匹配 (提及次数: 中频)
|
||||
**用户原话**:
|
||||
> "订阅费用高,对于轻度用户成本过高"
|
||||
> "免费版功能受限,基本无法实用"
|
||||
> "API调用费用过高"
|
||||
|
||||
**痛点描述**:用户付费后仍需大量人工编辑,感觉"花钱买了个需要返工的初稿"。
|
||||
|
||||
**影响人群**:小企业、个人创作者、独立开发者
|
||||
|
||||
**机会评估**:⭐⭐⭐⭐ (4/5) — 定价模式创新机会
|
||||
|
||||
---
|
||||
|
||||
### 5. 缺乏深度研究能力 (提及次数: 中频)
|
||||
**用户原话**:
|
||||
> "不能自动整合最新数据和事实核查"
|
||||
> "缺乏深度研究能力"
|
||||
|
||||
**痛点描述**:AI只能基于训练数据生成内容,无法实时获取和整合最新信息。
|
||||
|
||||
**影响人群**:分析师、研究人员、记者
|
||||
|
||||
**机会评估**:⭐⭐⭐⭐ (4/5) — RAG技术可解决
|
||||
|
||||
---
|
||||
|
||||
### 6. 多语言质量不一 (提及次数: 中频)
|
||||
**用户原话**:
|
||||
> "非英语内容质量明显较差"
|
||||
|
||||
**痛点描述**:英文内容质量尚可,但中文、日文等非拉丁语系的内容质量大幅下降。
|
||||
|
||||
**影响人群**:非英语用户(尤其是中日韩市场)
|
||||
|
||||
**机会评估**:⭐⭐⭐⭐ (4/5) — 巨大的未开发市场
|
||||
|
||||
---
|
||||
|
||||
### 7. 用户体验差 (提及次数: 低频)
|
||||
**用户原话**:
|
||||
> "界面复杂,功能繁多但不够直观"
|
||||
> "学习曲线陡峭"
|
||||
> "移动端体验差"
|
||||
|
||||
**痛点描述**:大多数AI写作工具的UX设计复杂,新手难以快速上手。
|
||||
|
||||
**机会评估**:⭐⭐⭐ (3/5) — 差异化竞争点
|
||||
|
||||
---
|
||||
|
||||
### 8. 伦理与版权担忧 (提及次数: 低频)
|
||||
**用户原话**:
|
||||
> "抄袭、版权和AI代写的道德问题"
|
||||
> "担心过度依赖AI会降低自身写作能力"
|
||||
|
||||
**痛点描述**:用户对AI生成内容的原创性、版权归属存在疑虑。
|
||||
|
||||
**机会评估**:⭐⭐⭐ (3/5) — 需要透明度和原创性保障
|
||||
|
||||
---
|
||||
|
||||
## 💡 机会洞察
|
||||
|
||||
1. **准确性优先**:做一个"事实核查+来源标注"功能的AI写作工具
|
||||
2. **个性化训练**:允许用户上传自己的文章,让AI学习个人风格
|
||||
3. **中文市场**:专注做高质量中文AI写作,避开英文红海
|
||||
4. **按效果付费**:不按字数/次数,而是按"用户满意度"或"发布率"收费
|
||||
5. **研究+写作一体化**:先自动调研,再生成有数据支撑的内容
|
||||
|
||||
---
|
||||
|
||||
## 📈 趋势观察
|
||||
|
||||
- 用户对"通用AI写作"的热情在降温,转向"垂直场景AI助手"
|
||||
- "AI检测"成为新需求 — 用户担心内容被标记为AI生成
|
||||
- 协作功能成为新卖点 — 团队写作需求增长
|
||||
- 中文AI写作工具市场仍有巨大空间
|
||||
@@ -0,0 +1,365 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
用户痛点自动抓取与分析工具
|
||||
从 Reddit、Hacker News 等平台采集用户评论,用 LLM 提取痛点。
|
||||
|
||||
用法:
|
||||
python3 pain_point_scraper.py --topic "AI写作工具" --sources reddit,hn --limit 20
|
||||
python3 pain_point_scraper.py --topic "OKX交易" --sources reddit --limit 30 --output report.md
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
import requests
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# 配置
|
||||
# ─────────────────────────────────────────────
|
||||
|
||||
# LLM API (使用本地 Ollama 或 LM Studio)
|
||||
LLM_API_URL = "http://192.168.199.100:11434/v1/chat/completions"
|
||||
LLM_MODEL = "gemma-4-26b-a4b-it-4bit"
|
||||
LLM_API_KEY = "" # 本地服务通常不需要
|
||||
|
||||
# 如果本地不可用,fallback到远程
|
||||
LLM_FALLBACK_URL = "https://token-plan-cn.xiaomimimo.com/v1/chat/completions"
|
||||
LLM_FALLBACK_MODEL = "mimo-v2.5-pro"
|
||||
LLM_FALLBACK_KEY = "tp-cd64i50fo6ifihhiupspq9dypmzeud3u77tia5mlz0rb572u"
|
||||
|
||||
HEADERS = {
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
|
||||
}
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# Reddit 采集
|
||||
# ─────────────────────────────────────────────
|
||||
|
||||
def scrape_reddit(topic: str, limit: int = 20) -> list[dict]:
|
||||
"""从 Reddit 搜索相关讨论"""
|
||||
results = []
|
||||
|
||||
# 使用 Reddit JSON API (无需认证)
|
||||
url = "https://www.reddit.com/search.json"
|
||||
params = {
|
||||
"q": topic,
|
||||
"sort": "relevance",
|
||||
"t": "month", # 最近一个月
|
||||
"limit": min(limit, 25),
|
||||
"type": "link"
|
||||
}
|
||||
|
||||
try:
|
||||
resp = requests.get(url, params=params, headers=HEADERS, timeout=15)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
|
||||
for post in data.get("data", {}).get("children", []):
|
||||
d = post.get("data", {})
|
||||
results.append({
|
||||
"source": "Reddit",
|
||||
"title": d.get("title", ""),
|
||||
"text": d.get("selftext", "")[:500],
|
||||
"score": d.get("score", 0),
|
||||
"comments": d.get("num_comments", 0),
|
||||
"url": f"https://reddit.com{d.get('permalink', '')}",
|
||||
"subreddit": d.get("subreddit", ""),
|
||||
"created": datetime.fromtimestamp(d.get("created_utc", 0)).isoformat()
|
||||
})
|
||||
|
||||
print(f" ✅ Reddit: 获取 {len(results)} 条", file=sys.stderr)
|
||||
except Exception as e:
|
||||
print(f" ❌ Reddit 采集失败: {e}", file=sys.stderr)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# Hacker News 采集
|
||||
# ─────────────────────────────────────────────
|
||||
|
||||
def scrape_hn(topic: str, limit: int = 20) -> list[dict]:
|
||||
"""从 Hacker News 搜索相关讨论"""
|
||||
results = []
|
||||
|
||||
url = "https://hn.algolia.com/api/v1/search"
|
||||
params = {
|
||||
"query": topic,
|
||||
"tags": "story",
|
||||
"hitsPerPage": min(limit, 30),
|
||||
"numericFilters": "created_at_i>" + str(int(time.time()) - 30*86400)
|
||||
}
|
||||
|
||||
try:
|
||||
resp = requests.get(url, params=params, timeout=15)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
|
||||
for hit in data.get("hits", []):
|
||||
results.append({
|
||||
"source": "Hacker News",
|
||||
"title": hit.get("title", ""),
|
||||
"text": (hit.get("story_text") or "")[:500],
|
||||
"score": hit.get("points", 0),
|
||||
"comments": hit.get("num_comments", 0),
|
||||
"url": hit.get("url", f"https://news.ycombinator.com/item?id={hit.get('objectID', '')}"),
|
||||
"author": hit.get("author", ""),
|
||||
"created": hit.get("created_at", "")
|
||||
})
|
||||
|
||||
print(f" ✅ HN: 获取 {len(results)} 条", file=sys.stderr)
|
||||
except Exception as e:
|
||||
print(f" ❌ HN 采集失败: {e}", file=sys.stderr)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# Product Hunt 采集 (通过搜索)
|
||||
# ─────────────────────────────────────────────
|
||||
|
||||
def scrape_producthunt(topic: str, limit: int = 10) -> list[dict]:
|
||||
"""从 Product Hunt 搜索相关产品评论"""
|
||||
results = []
|
||||
|
||||
# 使用 Google 搜索 Product Hunt 上的内容
|
||||
url = "https://www.google.com/search"
|
||||
params = {
|
||||
"q": f"site:producthunt.com {topic} review complaints",
|
||||
"num": min(limit, 10)
|
||||
}
|
||||
|
||||
try:
|
||||
resp = requests.get(url, params=params, headers=HEADERS, timeout=15)
|
||||
# Google 可能会block,所以这里简单处理
|
||||
if resp.status_code == 200:
|
||||
# 简单提取标题
|
||||
import re
|
||||
titles = re.findall(r'<h3[^>]*>(.*?)</h3>', resp.text)
|
||||
for t in titles[:limit]:
|
||||
clean = re.sub(r'<[^>]+>', '', t)
|
||||
if clean and len(clean) > 10:
|
||||
results.append({
|
||||
"source": "Product Hunt",
|
||||
"title": clean,
|
||||
"text": "",
|
||||
"score": 0,
|
||||
"comments": 0,
|
||||
"url": "",
|
||||
"created": ""
|
||||
})
|
||||
|
||||
print(f" ✅ Product Hunt: 获取 {len(results)} 条", file=sys.stderr)
|
||||
except Exception as e:
|
||||
print(f" ❌ Product Hunt 采集失败: {e}", file=sys.stderr)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# LLM 分析
|
||||
# ─────────────────────────────────────────────
|
||||
|
||||
def call_llm(prompt: str, api_url: str = None, model: str = None, api_key: str = None) -> str:
|
||||
"""调用 LLM API 进行分析"""
|
||||
api_url = api_url or LLM_API_URL
|
||||
model = model or LLM_MODEL
|
||||
api_key = api_key or LLM_API_KEY
|
||||
|
||||
headers = {"Content-Type": "application/json"}
|
||||
if api_key:
|
||||
headers["Authorization"] = f"Bearer {api_key}"
|
||||
|
||||
payload = {
|
||||
"model": model,
|
||||
"messages": [
|
||||
{"role": "system", "content": "你是一个专业的用户研究分析师。你擅长从用户评论中提取痛点、需求和机会。请用中文回答。"},
|
||||
{"role": "user", "content": prompt}
|
||||
],
|
||||
"temperature": 0.3,
|
||||
"max_tokens": 4000
|
||||
}
|
||||
|
||||
try:
|
||||
resp = requests.post(api_url, json=payload, headers=headers, timeout=120)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
return data["choices"][0]["message"]["content"]
|
||||
except Exception as e:
|
||||
print(f" ⚠️ 主API失败 ({e}),尝试fallback...", file=sys.stderr)
|
||||
# Fallback
|
||||
try:
|
||||
fallback_headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Bearer {LLM_FALLBACK_KEY}"
|
||||
}
|
||||
payload["model"] = LLM_FALLBACK_MODEL
|
||||
resp = requests.post(LLM_FALLBACK_URL, json=payload, headers=fallback_headers, timeout=120)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
return data["choices"][0]["message"]["content"]
|
||||
except Exception as e2:
|
||||
return f"❌ LLM 分析失败: {e2}"
|
||||
|
||||
|
||||
def analyze_pain_points(items: list[dict], topic: str) -> str:
|
||||
"""用 LLM 分析采集到的数据,提取痛点"""
|
||||
|
||||
# 构建分析prompt
|
||||
reviews_text = ""
|
||||
for i, item in enumerate(items[:30], 1): # 最多30条,避免token超限
|
||||
reviews_text += f"\n--- [{i}] {item['source']} | 👍{item['score']} 💬{item['comments']} ---\n"
|
||||
reviews_text += f"标题: {item['title']}\n"
|
||||
if item.get('text'):
|
||||
reviews_text += f"内容: {item['text'][:300]}\n"
|
||||
|
||||
prompt = f"""请分析以下关于"{topic}"的用户评论/讨论,提取用户痛点、需求和机会。
|
||||
|
||||
## 原始数据
|
||||
{reviews_text}
|
||||
|
||||
## 分析要求
|
||||
|
||||
请按以下格式输出:
|
||||
|
||||
### 📊 概览
|
||||
- 总评论数:N
|
||||
- 主要痛点数:N
|
||||
- 整体情绪:正面/负面/混合
|
||||
|
||||
### 🔥 TOP 痛点(按严重程度排序)
|
||||
|
||||
对每个痛点:
|
||||
1. **痛点标题**(一句话概括)
|
||||
2. **用户原话**(引用1-2条最能说明问题的原文)
|
||||
3. **痛点描述**(为什么这是问题)
|
||||
4. **影响人群**(谁会遇到这个问题)
|
||||
5. **现有解决方案**(有没有竞品在解决)
|
||||
6. **机会评估**(⭐1-5星,这个痛点值不值得做)
|
||||
|
||||
### 💡 机会洞察
|
||||
- 基于以上痛点,有哪些产品/功能机会
|
||||
- 有哪些未被满足的需求
|
||||
|
||||
### 📈 趋势观察
|
||||
- 近期讨论的热点变化
|
||||
- 用户关注点的转移
|
||||
|
||||
请用中文回答,保持分析的客观性和实用性。"""
|
||||
|
||||
return call_llm(prompt)
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# 报告生成
|
||||
# ─────────────────────────────────────────────
|
||||
|
||||
def generate_report(topic: str, items: list[dict], analysis: str) -> str:
|
||||
"""生成完整的Markdown报告"""
|
||||
|
||||
sources = {}
|
||||
for item in items:
|
||||
src = item["source"]
|
||||
sources[src] = sources.get(src, 0) + 1
|
||||
|
||||
source_summary = "、".join([f"{k}({v}条)" for k, v in sources.items()])
|
||||
|
||||
report = f"""# 🔍 痛点分析报告:{topic}
|
||||
> 数据来源:{source_summary} | 采集时间:{datetime.now().strftime('%Y-%m-%d %H:%M')} | 分析评论数:{len(items)}
|
||||
|
||||
---
|
||||
|
||||
{analysis}
|
||||
|
||||
---
|
||||
|
||||
## 📋 原始数据摘要
|
||||
|
||||
| # | 来源 | 标题 | 👍 | 💬 |
|
||||
|---|------|------|-----|-----|
|
||||
"""
|
||||
|
||||
for i, item in enumerate(items[:20], 1):
|
||||
title = item["title"][:50] + ("..." if len(item["title"]) > 50 else "")
|
||||
report += f"| {i} | {item['source']} | {title} | {item['score']} | {item['comments']} |\n"
|
||||
|
||||
report += f"\n*共 {len(items)} 条数据,显示前 20 条*\n"
|
||||
|
||||
return report
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# 主流程
|
||||
# ─────────────────────────────────────────────
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="用户痛点自动抓取与分析")
|
||||
parser.add_argument("--topic", "-t", required=True, help="分析主题/关键词")
|
||||
parser.add_argument("--sources", "-s", default="reddit,hn", help="数据源 (逗号分隔: reddit,hn,producthunt)")
|
||||
parser.add_argument("--limit", "-l", type=int, default=20, help="每个源采集数量")
|
||||
parser.add_argument("--output", "-o", help="输出文件路径 (默认stdout)")
|
||||
parser.add_argument("--raw", action="store_true", help="只输出原始数据,不做LLM分析")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
print(f"\n🔍 痛点分析:{args.topic}", file=sys.stderr)
|
||||
print(f"📡 数据源:{args.sources}", file=sys.stderr)
|
||||
print(f"📊 采集数量:每个源 {args.limit} 条\n", file=sys.stderr)
|
||||
|
||||
# 1. 采集数据
|
||||
all_items = []
|
||||
source_map = {
|
||||
"reddit": scrape_reddit,
|
||||
"hn": scrape_hn,
|
||||
"producthunt": scrape_producthunt
|
||||
}
|
||||
|
||||
for source in args.sources.split(","):
|
||||
source = source.strip().lower()
|
||||
if source in source_map:
|
||||
items = source_map[source](args.topic, args.limit)
|
||||
all_items.extend(items)
|
||||
else:
|
||||
print(f" ⚠️ 未知数据源: {source}", file=sys.stderr)
|
||||
|
||||
if not all_items:
|
||||
print("\n❌ 没有采集到任何数据", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
print(f"\n📊 总计采集: {len(all_items)} 条\n", file=sys.stderr)
|
||||
|
||||
# 2. 如果只输出原始数据
|
||||
if args.raw:
|
||||
output = json.dumps(all_items, ensure_ascii=False, indent=2)
|
||||
if args.output:
|
||||
with open(args.output, "w") as f:
|
||||
f.write(output)
|
||||
print(f"✅ 原始数据已保存到: {args.output}", file=sys.stderr)
|
||||
else:
|
||||
print(output)
|
||||
return
|
||||
|
||||
# 3. LLM 分析
|
||||
print("🧠 正在分析痛点...", file=sys.stderr)
|
||||
analysis = analyze_pain_points(all_items, args.topic)
|
||||
|
||||
# 4. 生成报告
|
||||
report = generate_report(args.topic, all_items, analysis)
|
||||
|
||||
if args.output:
|
||||
with open(args.output, "w") as f:
|
||||
f.write(report)
|
||||
print(f"\n✅ 报告已保存到: {args.output}", file=sys.stderr)
|
||||
else:
|
||||
print(report)
|
||||
|
||||
print(f"\n✅ 分析完成!", file=sys.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user