刷闲鱼捡漏的人都懂那种无力感:好价商品从上架到被秒,往往不超过三分钟,而你正开着会、挤着地铁、或者已经睡了。手速和在线时长,才是这条赛道真正的门槛。
有人写脚本定时搜关键词,但纯规则脚本只会把「400 元以内的 HHKB」全部推给你------里面混着坏轴的、缺键帽的、写着「价格随便标引流」的无效信息。规则能挡价格,挡不了语义,最后通知群被垃圾命中刷屏,人反而把提醒关了。
本文分享一套可直接落地的方案:关键词订阅 + 价格上限粗筛 + LLM 结构化初筛 + 命中推送,以 ai-goofish-monitor 为骨架,配置一份 YAML 就能跑起来。
一、判断标准:人肉刷新为什么抢不过自动化
先把差距量化一下,两种方式的成本对比如下:
| 维度 | 人肉刷新 | 脚本 + AI 初筛 |
|---|---|---|
| 在线时长 | 4~6 小时/天,且有盲区 | 24 小时,间隔可到分钟级 |
| 单条判断耗时 | 5~15 秒(看图、读描述) | 规则毫秒级,AI 约 1~2 秒 |
| 判断一致性 | 疲劳后标准下降 | 每条走同一套 prompt |
| 噪声承受力 | 十条垃圾后开始烦 | 噪声被自动丢弃,只看命中 |
- 真正的瓶颈不是手速:即使你全天盯着,也只覆盖了 1/4 的时间窗,而低价商品的上架时间是均匀分布的。
- 语义判断必须外包给模型:「自用无拆修」和「懂的来」信息量完全不同,正则表达不了这种差异。
- 人的价值在后置:机器做完 90% 的淘汰,人只对最终 3~5 条候选做「值不值得下单」的决策。
核心结论:自动化不是替你买,而是替你把 99% 的无效商品挡在通知之外。
二、整体架构:一条从关键词到推送的自动流水线
整个系统就是一条单向流水线,每一环都只做一件事:
YAML 规则 → 定时抓取 → 去重与价格粗筛 → LLM 结构化打分 → 命中推送
- 规则层 :
rules.yaml同时定义关键词、价格上限、期望成色,是唯一需要日常维护的文件。 - 抓取层:按关键词轮询闲鱼搜索接口,单轮只拉前若干条,控制请求频率,避免触发风控。
- 过滤层 :先用本地
seen_ids集合去重,再用max_price挡掉超预算商品,这一步不花钱。 - 决策层:只有通过粗筛的商品才进大模型,输出分数与档位。
- 触达层:分数达标才推送,附带标题、价格、理由和直达链接。
关键设计点是把贵的判断放到最便宜的判断之后 :大模型调用次数 = 抓取量 × 粗筛通过率,把粗筛通过率压到 10% 以下,成本就基本可以忽略。

三、规则配置:把「什么算好价」写成可复用的文件
配置先行:一份 YAML 同时驱动粗筛和后续的 AI 提示词,避免规则散落在代码里。
yaml
# rules.yaml:价格上限挡在最前,expect 字段后面喂给大模型
scan_interval: 180 # 抓取间隔,秒
keywords:
- name: 客制化键盘
words: ["HHKB", "Realforce", "Leopold"]
max_price: 400 # 超过此价不进 AI,直接丢弃
expect: "成色 9 成新以上、无缺键、含原装连接线"
- name: 中高端显卡
words: ["4070 Super", "7900 GRE"]
max_price: 3200
expect: "个人自用、非矿、有京东或天猫购买记录"
blacklist: ["中介", "代抢", "批发", "引流"]
llm:
model: qwen-plus
min_score: 7 # 低于 7 分不推送
几个容易踩的点:
- 价格上限要留议价空间 :闲鱼标价普遍虚高 10%~20%,
max_price设成心理价位的 1.15 倍更合理。 - 黑名单走粗筛而非 AI:含「中介」「批发」的商品语义上也无价值,正则一刀切最省钱。
- expect 写成可判定的条件:「成色好」这种没法判,「9 成新以上、无缺键」才能让模型给出稳定分数。
核心结论:配置文件就是产品需求文档,改配置不改代码,才能长期维护下去。
四、AI 初筛:让模型按固定字段给出可信结论
下面这段代码用 OpenAI 兼容接口调用通义千问,强制 JSON 输出并做分数过滤,适配 Python 3.10+:
python
import json, os
from openai import OpenAI
client = OpenAI(api_key=os.environ["DASHSCOPE_API_KEY"],
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1")
SYS = """你是二手捡漏助手。根据标题、描述、价格与买家期望输出 JSON:
score(0-10)、verdict(值得买/可疑/排除)、reason(40 字内)。
只依据文本信息判断,不要臆测卖家动机;信息不足时给 5 分并标注可疑。"""
def ai_screen(item, rule):
resp = client.chat.completions.create(
model=rule.get("model", "qwen-plus"),
messages=[{"role": "system", "content": SYS},
{"role": "user", "content": json.dumps({
"标题": item["title"], "描述": item["desc"],
"价格": item["price"], "期望": rule["expect"]},
ensure_ascii=False)}],
response_format={"type": "json_object"},
temperature=0)
r = json.loads(resp.choices[0].message.content)
return r if r["score"] >= rule["min_score"] else None
粗筛通过 → JSON 强约束 → 分数门槛二次过滤
- temperature 设 0:同一商品两次判断结论要一致,否则你无法评估阈值调没调对。
- 强制 JSON 而不是自由文本 :解析稳定,后续推送模板才能直接取
verdict和reason字段。 - 信息不足时打 5 分 :让模型承认不确定,比硬给高分更安全,误推一条假好价的代价远高于漏掉一条。

五、定时运行与推送:crontab 加多渠道提醒的落地
先用 crontab 把扫描任务挂成常驻作业,注意 cron 里 % 需要转义:
bash
# crontab -e:每 3 分钟一轮,日志按天归档便于复盘
*/3 * * * * cd ~/goofish && /usr/bin/python3 scan.py >> logs/$(date +\%F).log 2>&1
# 命中后推送到 Server酱,desp 里放标题、价格和理由
curl -s -X POST "https://sctapi.ftqq.com/${SENDKEY}.send" \
-d "title=闲鱼捡漏命中" -d "desp=${TITLE} | ${PRICE}元 | ${REASON} | ${URL}"
定时抓取 → 命中缓冲 → 一次性推送
推送渠道怎么选:
| 渠道 | 到达速度 | 接入成本 | 适合场景 |
|---|---|---|---|
| Server酱 / 企业微信机器人 | 秒级 | 一个 webhook | 单人手机提醒 |
| 钉钉群机器人 | 秒级 | webhook + 加签 | 多人共享捡漏信息 |
| Bark / ntfy | 秒级 | 装个 App | iOS/安卓原生弹窗 |
| 邮件 | 分钟级 | SMTP 账号 | 留档与事后复盘 |
- 同类命中合并推送:一轮扫描命中 3 条同类商品时打包成一条消息,避免通知轰炸。
- 推送里必须带直达链接:从通知到商品页的每一次跳转都在消耗你的抢购时间。
核心结论:提醒渠道的唯一指标是「到手机的速度」,其余都是次要的。

六、调优迭代:压住误杀率与重复提醒
跑一周后你会发现真正的问题不是抓不到,而是推得不准,需要按下面顺序调:
- 先看误杀 :把被模型判「排除」但你认为是好价的商品抽 20 条回看,多数是
expect写得太笼统,补具体条件即可。 - 再看漏杀 :漏掉的通常是价格上限卡太死,优先放宽
max_price而不是降min_score,后者会让噪声一起进来。 - 去重要按商品 ID 而非标题:同一商品改价重发会换 ID,可以再加「ID + 标题前 12 字」的模糊键兜底。
- 给模型看图能再提一档准确率:闲鱼详情图能暴露维修痕迹和实物质损,接入视觉模型后误推明显下降,但 token 成本翻倍,建议只对 8 分以上的候选补一次图片判断。
| 现象 | 高概率原因 | 处理动作 |
|---|---|---|
| 通知全是无效商品 | 只用了价格粗筛 | 补齐 expect,收紧 min_score |
| 明显的好价没推 | 价格上限过低 | 按标价虚高 15% 重算 max_price |
| 同一商品反复提醒 | 去重键失效 | 改用商品 ID 做 seen 集合 |
| 抓取经常空结果 | 触发风控或关键词太窄 | 拉长 scan_interval,放宽关键词 |
调优没有终点,但方向只有一个:让机器承担全部体力活,让人只做最后一条判断。
结语
闲鱼捡漏拼的从来不是谁更闲,而是谁能在商品上架的前三分钟内出现在页面上。把关键词、价格上限、黑名单写进一份 YAML,用 crontab 挂成常驻扫描,再让大模型用固定 JSON 格式做第一轮语义判定,这套链路一周内就能跑通,日常维护只需要改配置。
它的价值不只在省钱省时间,更在于把「刷到麻木」的重复劳动变成了「只处理 3 条候选」的决策工作,捡漏这件事终于回到了它本该有的样子。
先让机器替你盯盘,好价来的时候,你只需要决定买不买。