如何用Python构建需求信号挖掘工具:自动识别公开讨论中的购买意图
最近 Hacker News 上有一个 Show HN 项目,标题很直白:"I built a tool that finds people asking for what you sell"。翻译过来就是,我做了一个工具,专门帮你找到那些正在公开询问"你卖的东西"的人。
这类工具乍一听像销售玄学,其实背后是一条非常清晰的技术链路:定时获取公开讨论、识别文本中的购买意图、过滤掉无效信息、把线索推到你的聊天工具里。如果你正在做独立开发、垂直 SaaS、外包接单,或者是出海产品的市场运营,这条链路几乎每天都会用到。过去要靠人肉刷论坛、搜关键词,现在可以用一个几十行的 Python 脚本把它变成半自动流程。
这篇文章不评价那个项目本身是否成功,而是从工程实现的角度拆解它:如果自己动手做一个"需求信号挖掘工具",整体架构怎么设计、意图判断怎么做、代码怎么落地、有哪些容易踩的坑。读完你不仅能理解这类工具的原理,还能跑通一个最小可用的版本。
1. 这个工具到底在解决什么问题
1.1 传统找客户方式的三个痛点
先看一个真实的场景。假设你做了一个开发工具,比如一个轻量级的定时任务平台,你的目标用户是中小型研发团队。产品上线后,最痛苦的阶段不是写代码,而是"找第一批愿意试用的人"。
传统的做法是:
- 去技术社区、论坛、微信群、Telegram 群里搜索"定时任务""任务调度"等关键词。
- 手动翻开每一条帖子,判断发帖人到底是在做技术调研,还是真的有部署需求。
- 找到有需求的帖子后,再想办法私信对方,介绍自己的产品。
这套流程有三个明显问题:
- 搜索成本高。关键词搜出来大量内容是技术教程、源码分析、行业新闻,真正"想买方案"的内容可能只占 5%。
- 时效性差。很多用户发帖询问后,一两天内就自行选型了。你晚看到 24 小时,线索价值就大幅下降。
- 无法规模化。一个人一天最多翻几百个帖子,如果产品覆盖多个语言区域、多个平台,人工方式根本看不完。
这个 Show HN 项目的核心价值,恰好是把这三件事自动化了。
1.2 需求信号挖掘工具的本质
这类工具本质上是一个需求信号聚合器。它不负责替你成交,也不负责分析竞品,它只做一件事:从海量公开文本中,把"有人正在找解决方案"的帖子挑出来。
从技术视角来看,它是由以下四个模块组成的流水线:
- 数据接入:从 Reddit、HN、论坛、Twitter、Facebook Group、GitHub Issues 等公开来源获取文本。
- 意图识别:判断一条文本是"真实购买需求",还是"纯技术讨论""随便吐槽""内容营销软文"。
- 线索管理:对候选项去重、打分、记录状态,避免同一条线索被重复处理。
- 通知集成:把有价值的线索推送到 Slack、飞书、钉钉、邮箱,或者直接写入 CRM。
真正决定这类工具好坏的,不是第一层的"关键词搜索",而是第二层的"意图判断"。后面我会用一个完整的例子说明,为什么只靠关键词会漏掉大量高质量需求,又会混入大量垃圾信息。
1.3 什么样的人适合做这类工具
如果你符合下面任意一条,这类工具的思路对你是有价值的:
- 独立开发者:做了一款小产品,想低成本找到种子用户,而不是一上来就投广告。
- SaaS 创业者:产品处于冷启动期,需要在前 100 个用户身上验证需求真实性。
- 自由职业者或外包团队:想从技术咨询帖子里发现"愿意为方案付费"的潜在客户。
- 销售运营人员:负责海外市场的 social listening,需要把社交平台上的需求信号沉淀到 CRM。
反过来,它也不适合所有场景。如果你的产品是大众消费品、用户画像极度宽泛,或者客单价极高、需要复杂的招投标流程,那么公开文本里的"购买意图"就相当稀疏。工具找不到你还未定义的客户,目标客户画像越清晰,这种挖掘方式越有效。
2. 需求线索挖掘的核心概念
2.1 什么是需求信号
需求信号(buying intent signal)指的是用户在公开场景下表达出"我正在寻找某个问题的解决方案"的文本。这里的关键词是"正在"和"寻找"。
按信号强度大致可以分为三类:
| 信号类型 | 示例 | 价值 |
|---|---|---|
| 强需求 | "有没有推荐一个支持多租户的 SaaS 脚手架?" | 高,用户明确在找方案 |
| 中需求 | "我们的定时任务经常失败,团队准备找一个更稳定的方案" | 较高,但还需要接触确认 |
| 弱需求 | "想知道大家怎么处理定时任务的?" | 低,多为技术调研,不等于购买意图 |
工具的价值,就是尽可能多地识别前两类信号,同时把第三类信号控制在一个可接受的误报范围。
2.2 意图判定为什么比关键词搜索更关键
如果你只靠 job、schedule、task 这类关键词去搜索,你会发现两个问题:
- 召回率高但精确率低:大量技术帖子会包含这些词,但作者是在写教程,不是在找产品。
- 表达方式多样化:真实用户不一定会说"推荐一个 job scheduler",可能会说"我们的 cron 总出问题,想找个更省心的方案",关键词搜索很难覆盖这种语义变体。
解决思路是引入意图判定层。目前主流的做法有两类:
- 规则引擎:设计一套关键词权重、否定词表和打分逻辑。优点是速度快、成本低、结果可控;缺点是规则需要长期维护。
- 大语言模型判断:把帖子文本交给 LLM,让它输出是否为潜在线索、意图分数和判断理由。优点是泛化能力强,能理解上下文;缺点是有 API 成本,延迟更高。
更稳妥的方式是两者结合:先用规则层做粗筛,把明显不相关的帖子过滤掉,再对剩下的候选文本调用 LLM 精排。这样既控制成本,又保留语义理解的深度。
2.3 线索评分与去重
线索不是非黑即白的,应该有分数等级。比如:
- 分数 80-100:直接命中需求场景,建议优先跟进。
- 分数 50-79:有潜在价值,但需要进一步确认。
- 分数 0-49:大概率不是目标线索。
评分之后还要做去重。同一个人的帖子可能被多个数据源捕获,或者同一话题在短时间内被反复讨论。如果不去重,推送通知会变成垃圾消息,用户很快会关掉通知开关。
去重不能只看标题,更好的键是稳定识别的 ID。比如 Reddit 里的 post.id 或者完整链接 permalink。把已处理的 ID 存入数据库,每次处理前先查询,就能避免重复推送。
2.4 容易踩的两个误区
第一个误区是把关键词等同于需求。一条帖子包含"推荐"两个字,不代表发帖人想买你的产品。比如"我在写一篇推荐 Cron 工具的文章"就不是需求信号。要避免这个误区,必须在关键词过滤之外再加意图判断层。
第二个误区是只采集不跟进。很多初次动手的人把工具跑起来后,看到通知就以为完事了,结果发现转化率很低。原因很简单:文本里的需求是"模糊信号",你仍然需要人工回复、私聊、介绍产品。这个工具降低的是信息获取成本,不是销售成本。
3. 系统架构与常见实现路径
3.1 整体链路
一个最小可用的需求信号挖掘系统,数据流向如下:
在实际项目中,你还可以把"人工跟进"的结果回写到数据库,形成闭环:哪些线索最后变成了客户,当时的特征是什么。这些反馈数据会成为下一轮规则优化的基础。
3.2 数据源选型对比
不同的数据源,采集难度和价值差异很大:
| 数据源 | 获取方式 | 适合场景 | 注意点 |
|---|---|---|---|
| 官方 API(praw) | 海外技术社区、垂直 subreddit | API 频率受限,需要注册应用 | |
| Hacker News | 官方 API | 独立开发者、开发者工具 | API 免费且易用 |
| GitHub Issues | 官方 API | 发现"被同类产品困扰"的开发者 | 搜索 issue 时注意授权范围 |
| 自建论坛 | 爬虫或 RSS | 垂直行业论坛 | 需确认 robots 协议 |
| Twitter/X | 付费 API 为主 | 品牌监测、热点捕捉 | 门槛较高,非首选 |
对于初学者,我的建议是从 Reddit 的公开 subreddit 或 Hacker News 开始,因为接口稳定、规则清晰、对开发者友好,不需要处理复杂的反爬逻辑。
3.3 意图识别方案的取舍
意图识别是整个系统的核心技术含量所在。如果只做本地规则,实现成本低,但效果有限;如果全部用大模型判断,效果更好,但成本会随数据量上升。
一个比较务实的分层策略是:
- 召回层:用关键词和标题匹配,快速获取候选帖子。这一层允许误报,但要保证不遗漏核心候选。
- 粗筛层:用否定词表和简单规则,把明显无关的内容,如教程、招聘、纯讨论,过滤掉。
- 精排层:用 LLM 对剩余候选文本打分,输出
0-100的意图分数和判断理由。 - 人工复核:对高分线索做人工跟进,并把结果反馈到关键词库和规则里。
3.4 推送集成选择
对于个人开发者,推送方式按简单到复杂排序如下:
- 直接打印日志:适合刚跑通流程时调试。
- Webhook 到聊天机器人:用飞书、钉钉、Slack、企业微信的自定义机器人最简单,只需要一个 URL。
- 邮件通知:适合每日摘要模式,避免每一条线索都打扰你。
- 写入 CRM:当线索量增大后,可以对接简单 CRM,比如 HubSpot 的公开 API,或自己用 Airtable 存储。
4. 环境准备与前置条件
4.1 运行环境
本文示例使用 Python 3.9+,操作系统不限,Windows、macOS、Linux 都可以。需要你本机已经安装好 Python 和 pip。
核心依赖只有两个:
安装命令:
4.2 Reddit API 注册
使用 praw 调用 Reddit 官方 API,需要先注册一个应用。通用步骤是:
- 登录 Reddit,进入应用管理页面。
- 创建一个 "script" 类型的应用。
- 获取
client_id和client_secret。 - 记录你的 Reddit 用户名和密码(用于脚本授权)。
这里要提醒一句:不同时间、不同账户的界面布局可能不同,但核心概念不变。请以 Reddit 官方文档为准。如果你计划长期使用,务必控制请求频率,遵守平台 API 条款。
4.3 大模型 API 准备(可选但推荐)
如果你想让意图判断更准确,需要准备一个支持 OpenAI 兼容格式的大模型 API 服务。这个服务可以是你所在团队已经部署的模型网关,也可以是你在用的任何兼容服务。只需要三个配置项:
base_urlapi_keymodel_name
网络环境以你所使用的服务商约定为准,本文不展开说明特定服务接入方式。
5. 完整示例:从监听帖子到推送线索
下面我们实现一个最小可用的需求信号挖掘工具。它监听多个 subreddit 的新帖子,先做关键词召回,再用 LLM 判断购买意图,对高分线索去重并推送 Webhook。
5.1 目录结构
5.2 配置文件
5.3 数据源监听模块
scan_subreddit 做了召回层的过滤,只保留标题或正文中含有关键词的帖子。这一步不要追求精确,宁可多召回,因为后面有意图判定层做精排。
5.4 意图判定模块
意图判定模块有两种实现。先看规则版,适合没有 API 预算的情况。
再来看 LLM 版本。它把文本交给模型,要求输出结构化 JSON,便于程序解析。
注意,我这里没有指定 response_format 参数,因为不同兼容接口支持程度不一样。你可以根据自己使用的模型网关能力决定是否补充。
5.5 去重存储模块
使用 SQLite 保存已处理的线索 ID,避免重复通知。
这里用 source_id 作为主键。在 Reddit 场景下,post.id 是全局唯一的,可以安全去重。
5.6 推送通知模块
为了演示,我先实现一个打印日志的版本,再实现 Webhook 版本。生产环境中可以直接使用 Webhook 版本。
这里使用的是飞书自定义机器人的消息格式。如果你用钉钉或 Slack,消息字段会不同,但思路一致:构造一个 JSON,POST 到机器人地址即可。
5.7 主流程串联
主流程很简单:
- 遍历每个 subreddit,拿到候选帖子。
- 用规则层粗筛,排除明显无价值文本。
- 如果配置了 LLM,再调用 LLM 做语义精排。
- 分数低于 60 的丢弃,分数达标且不重复的入库并推送。
6. 运行结果与效果验证
6.1 运行方式
在项目根目录执行:
如果配置正确,你会看到类似下面的日志,注意实际输出取决于你监听的分区和当时的帖子内容:
再次执行时,同一条帖子会因为 source_id 已存在于 leads.db 而被跳过,不会重复推送。
6.2 判断成功的标准
不要只看"有没有收到推送",要从三个维度评估:
- 是否有真实线索被找到:比如收到了"我在找 XX 工具替代方案"这样的帖子,而不是只有教程帖。
- 误报率是否可接受:统计前 100 条推送中,真正值得回复的比例。如果低于 20%,说明关键词规则太宽泛,或 LLM 阈值太低。
- 去重是否生效:第二次运行不应该再收到同一条帖子的推送。
6.3 失败时第一排查顺序
如果运行报错,按这个顺序排查:
- 检查
config.py里的 API 凭据是否为空。 - 检查网络是否能够访问 Reddit API 和 LLM API。
- 检查 pip 依赖是否安装完整。
- 查看异常堆栈中第一个报错行,确认是网络问题、权限问题还是解析问题。
对于 Webhook 推送失败,最直接的办法是用 curl 手动发一条测试消息:
如果手动发送成功,说明问题不在 Webhook 地址,而在程序构造的请求体格式。
7. 常见问题与排查思路
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| Reddit API 返回 401 | client_id/secret 不正确,或应用类型不是 script | 核对 Reddit 后台的应用配置 | 重新生成凭据,确认应用类型 |
| 收到的线索大量无效 | 关键词规则太宽泛 | 打印被误判的文本样本 | 增加否定词表,提高 LLM 阈值 |
| 同一线索重复推送 | 去重字段不稳定 | 检查 source_id 是否是 post.id |
改用 post.id 或 permalink 作为唯一键 |
| LLM 接口超时 | 并发调用过多或模型响应慢 | 查看接口日志与平均响应时间 | 降低频率,或把超时时间调大 |
| Webhook 推送失败 | 机器人 token 失效 / 网络不通 | 用 curl 手动测试 | 更新 webhook 地址,增加重试机制 |
| 跑了很久一条线索都没有 | subreddit 选择太冷门,或关键词覆盖面太窄 | 用 Reddit 网页搜索验证这些词是否有新帖 | 增加分区别表,扩展同义关键词 |
生产环境中,建议给 Webhook 推送加一个简单的重试机制。比如失败时把消息写入本地队列,下轮运行再补推。
8. 最佳实践与工程建议
8.1 数据采集合规边界
这个工具采集的是公开平台上的公开内容,但仍然要注意边界:
- 优先使用官方 API:不要绕过平台的付费墙、登录墙或反爬限制。
- 控制请求频率:即使有 API 配额,也不要高频轮询,否则容易被限流。
- 关注平台条款:不同平台对自动化工具、数据使用和商业用途的定义不同,发布到生产环境前先读一遍条款。
- 不存储敏感信息:只保留"文本内容 + 链接 + 意图分数"这类线索信息,避免保存用户名等可以关联到个人的数据。
如果你打算把这类工具作为商业产品发布,建议咨询法律意见。它能降低你的工程风险。
8.2 线索质量与阈值调优
"阈值定多高"取决于你处理线索的能力。线索数量少但质量高,适合个人开发者;线索数量多但需要二次筛选,适合有销售运营团队的公司。
一个实用的迭代路径是:
- 先用一个宽松阈值跑一周,收集原始输出。
- 每天人工给线索打分:这个线索要是给你,你愿不愿意花 5 分钟回复。
- 把人工评分与模型分数对比,找出被高估和低估的样本。
- 根据样本调整关键词库、否定词表和 LLM 提示词。
这套方法本质上是把模型当作"初筛助手",而不是"最终决策者"。
8.3 推送与跟进机制
推送一定要克制。如果每条线索都立刻推送,一天 20 次,你很快会关掉通知。更好的方式是:
- 低分线索累积为日报:每天固定时间发送一次汇总。
- 高分线索实时推送:只有 80 分以上才触发实时通知。
- 记录跟进状态:在数据库里加一个
status字段,标注new、contacted、converted、invalid,方便后续复盘。
8.4 生产环境注意事项
如果要长期运行,而不是只在本地跑,要注意以下几点:
- 用定时任务运行:比如每 30 分钟执行一次
python main.py,避免常驻进程带来的资源占用。 - 异常捕获与日志:在
main.py里加上try/except和日志输出,别让一次 API 错误中断整轮扫描。 - 准备降级方案:LLM 服务不可用时,自动降级到规则判断,保证基本功能可用。
- 数据备份:SQLite 文件虽小,但它是线索的历史记录,建议每天备份一次。
9. 总结与后续学习方向
这个 Show HN 项目从一开始就把"找客户"这件事拆解成了一个清晰的工程问题:公开文本从哪来、如何判断购买意图、如何控制噪音、如何及时通知。它没有制造新的概念,而是把已有的 API、模型和消息机器人组合成了一条可以被复用的流水线。
如果你今天想动手实践,建议按这个节奏来:
- 先不接 LLM,用规则版把 Reddit 监听跑通,感受一下线索质量和误报率。
- 再接入 LLM 做精排,对比规则版和 LLM 版的差异。
- 然后引入 SQLite 去重和 Webhook 推送,让系统具备基本可用的状态。
- 最后,把每天的真实线索存下来,持续优化提示词和阈值。
最近这几年,独立开发者之间的竞争已经从前端界面转向了"谁能更快找到真实需求"。这类工具的价值,不在于它用了什么高深算法,而在于它让需求发现从"靠运气刷帖"变成了"有节奏的工程流程"。你可以把它当作一个小玩具,也可以当作未来销售体系里最前置的一个环节。关键在于,你愿不愿意用工程化的方式,认真对待"找客户"这件事。