飞牛NAS部署闲鱼AI监控:Docker盯价与大模型筛选全攻略
发布时间:2026/9/29 10:21:27来源:尧图网络
玩摄影的朋友应该都有这种经历在闲鱼看中一支合适的定焦镜头价格也谈得差不多了想着“再等等、再看看”结果第二天点开商品详情显示“已卖出”。更气人的是隔几天又刷到同样的镜头价格还贵了几百。蹲了一阵子之后我决定不再手动刷了直接在飞牛NAS上搭了一套闲鱼AI监控自动盯关键词、盯价格变化再用大模型把一堆“看起来便宜但实际没价值”的商品过滤掉最后把真正值得看的商品推到手机上。跑通之后效果非常明显这篇文章就把整个方案从需求拆解到模块实现、公网访问配置再到踩坑复盘完整记录下来给也想让NAS干点正事的朋友做个参考。1. 先拆清楚这套方案到底要解决什么问题1.1 闲鱼盯价为什么需要自动化闲鱼跟传统电商平台最大的区别是“人和物的不确定性”每件商品都是独立卖家价格没有统一标准上架和下架完全靠个人行为驱动。一支热门镜头挂出来可能两三个小时就被秒了一个冷门配件反而可能挂半年都没人问。人工盯的最大问题在于你不可能保持全天候的注意力更不可能同时盯住七八个关键词、十几件意向商品。自动化盯价解决的不只是“速度”还有“广度”和“可持续性”。用脚本轮询搜索接口可以覆盖多关键词、多商品每隔十几分钟记录一次价格和库存状态形成一个动态的“商品池”。当池子里出现新上架的商品、已有商品降价、或者商品突然下架系统都能第一时间感知并推送通知。这套能力不是单纯把你从“手动刷新”里解放出来而是把“盯”这个动作变成一个可持续运行的基础设施。这里要注意用途边界这套方案定位是个人闲置交易中的比价和参考辅助用来帮你第一时间发现心仪商品、判断价位是否合理。别拿它去做批量采集或黄牛囤货的生意那既违背平台规则也容易给自己带来麻烦。1.2 为什么底层平台选飞牛NAS而不是别的有了需求之后第一件事是选承载平台。我最终选了飞牛NASfnOS原因有三个。第一成本与功耗。家里本来就有台闲置的x86小主机刷上飞牛系统之后整机功耗也就十几瓦比专门租一台云服务器划算得多也比一直开着主力电脑省电。NAS本身就是为7×24运行设计的跑这种持续监控任务非常合适。第二Docker支持完善。飞牛OS基于Debian自带Docker管理界面镜像拉取、容器管理、日志查看都挺顺手。我要跑的盯价脚本、大模型服务、反向代理全都可以容器化部署互不干扰升级也方便。第三数据自持。所有采集记录、模型推理结果、历史价格曲线都存在自己硬盘上不会被某家云厂商绑定。飞牛系统本身免费应用商店里还能装不少实用工具整体是“一台设备解决多个需求”的思路。如果你手头没有飞牛设备其实群晖、威联通甚至一台刷了Linux的小主机也能复刻这套方案只是飞牛在Docker和网络配置上对新手更友好一些。1.3 整套系统由哪几个模块组成整体看这套系统可以拆成三个核心模块加一个入口。盯价采集模块负责定时请求搜索、解析商品信息、去重入库并监控价格和库存变化。大模型筛选模块把采集到的商品信息喂给大模型让模型判断“值不值得看”输出推荐结论和理由。通知与公网模块把筛选结果通过Webhook推到手机同时通过DDNS和IPv6把管理页面暴露到公网方便随时查看。我特意把模块拆得很独立因为每个环节都有独立替换的空间。比如盯价脚本可以换语言重写大模型可以在本地Ollama和云端API之间切换通知通道可以从企业微信换到Telegram。模块间只通过简单的JSON数据格式通信演进成本很低。2. 环境准备飞牛 NAS 上先把三件套配好2.1 Docker 与容器网络的基本配置飞牛OS安装完成后桌面上的“Docker”应用就是管理入口。新建项目时可以直接粘贴docker-compose.yml比起一个个创建容器再手动配网络省事很多。先做一个最小骨架version: 3.8 services: monitor: image: python:3.12-slim container_name: xianyu-monitor volumes: - ./app:/workspace - ./data:/data working_dir: /workspace command: python main.py restart: unless-stopped environment: - TZAsia/Shanghai webhook-relay: image: nginx:alpine container_name: webhook-relay volumes: - ./nginx.conf:/etc/nginx/conf.d/default.conf ports: - 8080:80 restart: unless-stopped这里有两个细节值得提一是容器时区很多基础镜像默认是UTC时区如果不设置TZ环境变量Python的datetime.now()会跟本地时间差8小时后续定时任务和日志时间都会错乱。二是我用了一个简单的Nginx容器做Webhook中转后面讲公网入口时会展开说明。2.2 部署大模型服务本地Ollama与Dify二选一大模型筛选这块我的建议是先想清楚自己要“裸调用”还是“走编排平台”。如果你只想快速跑通直接在NAS上部署Ollama拉一个7B级别的中文模型就够用。命令很简单docker run -d -v /vol1/ollama:/root/.ollama -p 11434:11434 \ --name ollama ollama/ollama docker exec ollama ollama pull qwen2.5:7bOllama自带HTTP API/api/generate和/api/chat都能直接调用返回JSON也容易解析。缺点是模型效果受限于NAS的内存和CPU7B模型在纯CPU推理时速度偏慢一条商品可能要等几十秒。如果你想有更好的调试体验、后续还要做多模型切换和可视化那就上Dify。Dify本身是一个大模型应用编排平台它在NAS上跑起来之后可以把Ollama作为模型供应商接进去也可以接云端API。你用Dify编排好的工作流会自动生成标准的HTTP调用接口后面盯价脚本只需要往这个接口发请求不用关心底层模型怎么换。我自己的选择是Ollama做本地兜底Dify做正式链路日常稳定用Dify工作流偶尔本地测试直接调Ollama。两者并不互斥Dify内置了对Ollama的支持配置起来就是填一个Base URL的事。2.3 准备好通知通道企业微信和钉钉Webhook手机推送是整个监控闭环的最后一公里。我用的方案是企业微信群机器人Webhook创建流程非常快企业微信里随便建一个群群设置里添加“群机器人”复制Webhook地址然后往这个地址POST一段JSON就能收到消息。curl -X POST \ https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key你的key \ -H Content-Type: application/json \ -d {msgtype: text, text: {content: 监控服务已启动}}钉钉的群机器人路径也类似如果你更习惯用钉钉改成钉钉的Webhook地址即可。这类Webhook的延迟基本在1秒以内稳定性也不错作为个人项目的通知通道绰绰有余。3. 核心模块一自动盯价脚本的设计与实现3.1 搜索、解析、去重一个最小可用的抓取循环盯价脚本的核心就是一个循环搜索关键词 → 解析结果 → 去重入库 → 等待下一轮。import time import json import sqlite3 import requests from datetime import datetime KEYWORDS [索尼 50mm f1.4, 适马 85mm f1.4, 富士 X100VI] def init_db(): conn sqlite3.connect(/data/items.db) conn.execute( CREATE TABLE IF NOT EXISTS items ( item_id TEXT PRIMARY KEY, title TEXT, price REAL, seller TEXT, region TEXT, url TEXT, first_seen TEXT, last_seen TEXT, last_price REAL ) ) return conn def fetch_search(keyword): # 这里按普通浏览器请求的方式构造具体接口细节不展开 # 核心是拿到商品的 itemId、标题、价格、卖家信息 url https://www.goofish.com/search headers {User-Agent: Mozilla/5.0 ...} resp requests.get(url, params{q: keyword}, headersheaders, timeout10) return resp.json().get(items, []) def dedupe_and_store(conn, items): new_items [] for it in items: item_id it.get(itemId) if not item_id: continue cur conn.execute(SELECT price FROM items WHERE item_id ?, (item_id,)) row cur.fetchone() now datetime.now().isoformat() if row is None: conn.execute( INSERT INTO items VALUES (?,?,?,?,?,?,?,?,?), (item_id, it.get(title), it.get(price), it.get(seller), it.get(region), it.get(url), now, now, it.get(price)) ) new_items.append(it) else: old_price row[0] if old_price ! it.get(price): conn.execute(UPDATE items SET price ? WHERE item_id ?, (it.get(price), item_id)) # 标记降价商品下一步交给筛选模块处理 it[price_drop] True new_items.append(it) conn.commit() return new_items if __name__ __main__: conn init_db() while True: for kw in KEYWORDS: try: items fetch_search(kw) fresh dedupe_and_store(conn, items) if fresh: # 把新商品写入待筛选队列由大模型模块消费 with open(/data/pending.jsonl, a) as f: for item in fresh: f.write(json.dumps(item) \n) except Exception as e: print(f{datetime.now()} fetch error: {e}) time.sleep(60) # 避免短时间高频请求 time.sleep(600)框架原理很简单但有几个设计点我得特别说明。第一是SQLite做持久化。你肯定不想每次重启脚本就把之前见过的商品全忘了那样每次重启都会收到一大波重复推送。用SQLite记录item_id天然支持去重同时通过last_price字段可以判断价格是涨还是降。第二是待筛选队列。脚本本身不做价值判断它只负责把新商品和降价商品写入pending.jsonl。大模型筛选模块作为独立消费者读取这个文件两个模块解耦后即使AI偶尔卡一下盯价采集也不会被拖慢。3.2 价格变化追踪与库存检测盯价不只是盯“新上架”降价提醒反而更能捡到漏。许多卖家挂出的价格本来就虚高挂着挂着没人问自然会主动调低心理预期。能做降价判断的关键就是上节代码里的last_price字段。我在每次循环里都更新最后看到的时间和当前价格一旦当前价格低于历史价格就标记为“降价商品”推给下一层处理。库存检测更简单如果一个item_id连续两轮没有出现在搜索结果里说明商品要么卖掉了要么下架了这时候可以推一条“商品消失”通知避免你还在惦记一个已经不存在的链接。3.3 关于访问频率、风控与合规的实操建议这一节我必须多说几句。自动化访问任何商业平台都存在被风控的可能。我的经验是个人轻量比价场景完全可控前提是别贪。轮询间隔不要低于10分钟最好加上随机抖动比如600到900秒之间随机取一个值。脚本内连续请求不要超过三个关键词就休息一会儿失败重试要带指数退避而不是疯狂重连。另外要明确一点这类脚本只适合做个人维度的信息聚合和比价参考不适合批量采集、商业分析和违背平台规则的自动化交易。尊重平台服务条款保持正常的访问频率本质上跟“我每天自己刷几次闲鱼”没有区别只是用程序帮我盯得更勤快一些。4. 核心模块二用大模型做商品筛选把“盯”变成“懂”4.1 为什么筛选这步必须交给大模型盯价脚本把商品捞回来之后面临一个更现实的问题信息太多了多到根本来不及看。我设置三个关键词一天下来可能捞到上百条新商品其中一半是镜头盖、皮套、转接环这种配件剩下的一半里又夹杂着商家批量挂的“全新未拆”和明显高于市场价的“传家宝”。最初我用正则和规则引擎做过滤比如“标题包含光圈数字”“价格区间在2000到5000之间”。规则跑起来确实快但很快发现致命弱点它判断不了“值不值”。一个卖家描述里写着“国行在保、箱说全、快门数两千”价格比市场均价低了15%这明显是值得蹲的好东西另一个标题写“99新、几乎没用过”点进去发现是“港版无保修”甚至可能是翻新机。让规则引擎去区分这些你得写几百条规则还未必覆盖所有情况。大模型不同。它能把标题、价格、卖家信用、商品描述、发货地综合起来做一个整体判断甚至能给出“这价格为什么合理/不合理”的理由。比如看到“快门数两千、箱说全、国行在保”这种描述模型知道这是影响镜头二手价的关键加分项看到“只拆封、无配件、个人自用”这种模糊描述模型会建议谨慎。这种多维度的判断能力恰好是二手交易场景最需要的。4.2 从Ollama到Dify模型调用与流式输出的接入细节看完一条商品我先把信息压缩成结构化字段再交给模型判断。直接调Ollama比较轻import requests def ask_model(item): prompt f 判断这条闲鱼商品是否值得关注 标题{item[title]} 价格{item[price]} 卖家{item[seller]} 描述{item[desc][:50]} 请输出JSON回复包含 recommend(boolean)、score(0-100)、reason(一句话)。 resp requests.post( http://ollama:11434/api/generate, json{model: qwen2.5:7b, prompt: prompt, stream: False} ) return resp.json()[response]从NAS的另一个容器直接访问http://ollama:11434前提是两者在同一个Docker网络里。跑通这一步之后你会发现本地模型的速度和效果都能接受但输出格式偶尔会飘JSON解析容易报错这个坑我们放到6.2节细说。如果你走了Dify链路流程是先用Dify画布搭建一个“商品筛选”工作流把“标题、价格、描述”作为输入变量模型节点负责生成判断最后用模板输出结构化文本。保存后Dify提供一个标准的HTTP API地址脚本改调用这个 API 就行resp requests.post( http://dify:5001/v1/workflows/run, headers{Authorization: Bearer app-xxx}, json{inputs: item, response_mode: streaming} )Dify的API天然支持流式输出SSE也就是边生成边返回。如果你打算在Web页面上实时展示模型的推荐理由流式能让用户第一眼就看到“值”还是“不值”的判断不用等模型把整段话推理完。前端监听事件流拿到一个数据块就渲染一段页面关闭时调用AbortController.abort()取消请求避免服务器继续白跑计算。4.3 筛选提示词与上下文工程让模型稳定输出结构化结果大模型筛选能不能稳定工作90%取决于提示词和上下文设计。我调过很多版提示词最终稳定运行的是这个模板你是我的个人二手购物助手。我会给你一条闲鱼商品信息包括标题、价格、卖家信用、商品描述片段、发货地。 请从“是否值得我花时间查看”的角度判断只输出JSON {recommend: true或false, score: 0到100的整数, reason: 不超过20个字的一句话理由, suggest_price: 你对该商品合理二手价的估计} 判断标准 1. 只推荐个人卖家的真实闲置商品商家、代购、批发档口一律不推荐。 2. 价格明显超过同款平均价15%以上时recommend为false。 3. 描述中出现“正版”“国行”“箱说全”“个人自用”等正面信息可以加分。 4. 描述含糊、无实物图、提到“加微信”“线下交易”等风险信号recommend必须为false。 示例 输入{title:索尼 50mm f1.4 国行 箱说全,price:4200,...,desc:快门少 成色新 发票齐全} 输出{recommend: true, score: 85, reason:国行箱说全价格合理, suggest_price: 4200} 现在请分析 {结构化商品信息}这个提示词有几个设计细节明确“不推荐”的信号优先、给出一个可参考的示例、要求JSON输出。很多人直接让模型“判断商品是否靠谱”模型往往就泛泛而谈把判断标准拆成一条条硬规则后输出稳定性明显提升。上下文工程同样重要。原始商品描述可能有几百字其中大量内容是“个人闲置非商家”“不议价”“介意勿拍”这类噪声。我在喂给模型之前先提取出关键词、抽掉重复表述把上下文压缩到几十个字以内。这样既减少token消耗也让模型更容易聚焦重点。最近很多大模型支持的上下文越来越长但长上下文不等于判断更准输入干净比输入多更重要。5. 公网入口把监控服务从内网带到手机5.1 三种远程访问方案对比系统跑起来之后最自然的诉求就是“我人不在家也得能收到推送、能打开管理页面看看”。我对比过三种方案方案成本速度稳定性安全控制飞牛自带内网穿透免费或极低一般受中转节点影响一般依赖服务方IPv6 DDNS免费快直连高完全自控云服务器反向代理需要服务器月费快高完全自控最后我选了IPv6 DDNS理由是当前家庭宽带普遍已经分配了IPv6地址NAS只要配置好IPv6入口就能实现公网直接访问不需要额外购买服务器。速度上由于是点对点直连比走中转的穿透方案快得多。唯一的前提是你的NAS和路由器都支持IPv6家里宽带运营商没有把IPv6整个屏蔽。从2024年往后的使用体验看大部分运营商都默认开了IPv6这个条件基本都能满足。5.2 飞牛DDNS与路由器IPv6放行的具体配置飞牛OS把DDNS集成在系统设置里操作比在路由器上折腾DDNS服务简单很多。步骤如下打开飞牛OS的“设置 → 远程访问 → DDNS”添加一条记录。选择一个域名服务商可以注册一个便宜的域名比如每年几块钱的.top。填入域名的Access Key让系统能自动更新DNS记录。系统会把本机IPv6地址定期绑定到域名上地址变了也不用管。随后改路由器配置。这里不同品牌路由器界面差异比较大但核心操作就两个在“IPv6设置”里确认IPv6是开启状态并且给NAS分配一个固定的后缀比如通过MAC地址绑定。在“防火墙/安全”里添加入站规则放行NAS上对应端口的IPv6流量。我这里放行的是8080端口Webhook中转和443端口后续Web管理页面走HTTPS。我踩过一次“能ping通但打不开网页”的情况最后发现是路由器默认只放行IPv6的ICMP没有放行TCP端口流量。如果你也遇到类似情况优先去路由器的IPv6防火墙规则里找原因。如果想让管理页面好看一点可以在NAS上再跑一个Nginx Proxy ManagerNPM把多个服务的HTTP端口统一反向代理到443端口配合Let’s Encrypt自动签证书访问入口就变成https://你的域名既统一又安全。5.3 入口安全令牌校验、HTTPS与端口收敛把服务暴露到公网之后安全意识必须跟上。我的几个经验所有暴露到公网的管理页面都套一层访问令牌。Dify自带应用密钥NPM可以加Basic Auth哪怕是自建的简单页面也要加一个随机Token参数。除非有明确需求不要把SSH、Docker管理端口暴露到公网。我平时管理NAS都走内网真正需要远程维护时再临时打开用完立刻关闭。HTTPS证书必须有。NPM对接Let’s Encrypt之后会自动续期不需要手动干预。公网上没有HTTPS的入口容易被运营商或者中间设备干扰。定期看一眼NPM的访问日志确认没有异常IP在扫描你的入口。发现频繁的暴力尝试就直接封锁IP段。公网入口本质上是一个“门”你要做的不是把门做得特别华丽而是把门窗数量少到别人找不到再把剩下的门锁好。6. 全链路实测与踩坑复盘6.1 从纯内网测试到公网推送的全流程验证全套配置完成后我按这种顺序做了一轮端到端测试在NAS本机上手动执行一次盯价脚本确认能抓到商品、写入SQLite。把一个商品手动写入pending.jsonl观察大模型筛选模块是否读取并生成JSON推荐结果。把推荐结果推送到企业微信群确认手机能收到消息链接能跳转到闲鱼商品页。关闭NAS所在网络的WiFi改用手机流量访问https://我的域名确认IPv6直连生效。全流程跑通之后我把轮询间隔设为600到900秒随机值让它稳定跑了两周。这两周里它帮我抓到了一支价格明显低于市场均价的镜头推送消息通知到手机的下一刻我点进去东西还在。那一刻觉得前面的折腾都值了。6.2 排查链路实录三个让人印象深刻的坑坑一容器时区错乱导致定时任务总在错误时间执行现象是推送通知经常在下午才发出来而脚本计划凌晨就应该跑。排查时先看容器内时间执行docker exec xianyu-monitor date发现输出是UTC时间比北京时间慢8小时。虽然脚本里用的是time.sleep()循环不依赖cron但日志里打印的时间戳全是UTC排查问题非常误导。最终解法是给所有容器统一加TZAsia/Shanghai环境变量重建容器后一切正常。坑二IPv6间歇性不可达有一次在外面用手机流量访问管理页面正常但回家用同一个手机连接家中的WiFi时反而打不开。这个现象一开始很迷惑后来才意识到手机流量走的是运营商IPv6网络能直连NAS家中WiFi经过路由器时入站IPv6流量被防火墙拦住了。在路由器防火墙里放行对应端口后两种情况都能正常访问。这个坑的教训是排查公网访问问题一定要把“外网访问”和“内网访问”分开测才能快速定位是运营商路由、光猫还是路由器防火墙的锅。坑三大模型误判“盗版影印书籍”为值得购买系统跑了一周后推送里开始出现一批低价书籍模型判断“价格合理、值得关注”。但我点进去发现是明显影印盗版。问题出在提示词没有明确“判断商品本身是否合法合规”的维度。修复方式是在判断标准里新增一条如果商品疑似盗版、仿冒或存在版权风险直接给recommend: false理由里注明“疑似盗版”。加了这个约束后这类误判基本清零。这个坑说明筛选提示词不是写一次就完事要根据实际推送结果持续补充负向规则。6.3 这套架构还能继续往哪里延伸跑通这套闲鱼AI监控之后我发现底层的“采集 → AI判断 → 通知”架构其实是可以复用的模式。比如加一个网页看板用SSE流式实时渲染大模型给出的推荐理由配合AbortController在用户离开页面时及时取消推理请求比如把SQLite里的历史价格数据导出来画一条价格趋势曲线判断“现在该不该出手”再比如把企业微信通知换成Telegram Bot购买一张海外SIM卡通知渠道更稳定。我个人建议是先把最小闭环跑稳再考虑延伸功能。盯价加AI筛选看起来复杂实际上每一个模块都是独立的、可替换的真正值钱的是你对自己需求的拆解能力。如果你也有一台NAS在吃灰不妨从今天开始让它干点正事。
网站建设高端定制企业官网