1. 项目概述:一个解决信息过载的自动化智能摘要工具
每天一睁眼,手机里塞满了未读的公众号推送、新闻App的弹窗、RSS阅读器里堆积的未读条目,还有各种行业资讯网站更新的红点。这感觉就像站在一条信息洪流的中央,试图用一个小杯子去舀水,结果往往是手忙脚乱,最后什么也没留下。我相信这是很多信息工作者,尤其是技术从业者、产品经理、市场分析师,甚至是对特定领域保持关注的普通用户的共同痛点。我们不是缺少信息,而是缺少一种高效、精准、省力的方式,从海量噪音中提取出真正有价值的那部分“信号”。
今天要分享的,就是我最近在用的一个“信息减负”利器——Smart Digest。这是一个基于OpenClaw生态的智能技能(Skill),它的核心使命非常明确:帮你自动抓取、筛选、总结并推送你真正关心的资讯。你可以把它理解为一个高度定制化的、24小时在线的私人新闻编辑。你只需要告诉它你对什么感兴趣(比如“人工智能”、“新能源汽车”、“石油市场动态”),它就会自动从多个源头(主要是通过 SearXNG 搜索引擎和 RSSHub)抓取相关内容,利用 AI(默认是 Claude 3 Haiku 模型)生成简洁的中文摘要,然后按照你设定的时间,准时推送到你的飞书或 Telegram 聊天窗口里。
整个流程完全自动化,从数据获取到最终推送,无需人工干预。最吸引我的是它的“优雅降级”设计:即使你没有配置 AI 摘要的 API 密钥,它也能退而求其次,使用内容片段作为摘要,确保核心的信息聚合与推送功能不受影响。对于像我这样,既想享受 AI 带来的信息提纯便利,又对 API 调用成本比较敏感的用户来说,这种设计非常贴心。接下来,我将从设计思路、核心实现、实操部署到避坑经验,为你完整拆解这个项目,让你也能快速搭建起自己的个性化资讯流。
2. 核心设计思路与架构解析
2.1 为什么是“多源聚合”而非单一 RSS?
很多现有的资讯聚合工具,往往重度依赖 RSS 源。但现实情况是,高质量的独立博客越来越少,许多有价值的资讯散落在社交媒体、专业论坛和新闻网站中,而这些地方并不都提供标准的 RSS 输出。Smart Digest 选择SearXNG 作为主要数据源,这是一个非常聪明的设计。
SearXNG 是一个开源的元搜索引擎,它本身不收集信息,而是聚合来自谷歌、必应、维基百科等上百个搜索引擎和网站的结果。这意味着,你的一次搜索,实际上是在并行查询数十个信息源。对于资讯抓取来说,这极大地提高了覆盖面和时效性。项目将其作为“首选”数据源,正是看中了其覆盖面广、结果去偏见、可自托管的特性。自托管 SearXNG 后,你完全掌控搜索过程,无需担心外部 API 的调用限制或隐私问题。
当然,任何单一源都有失效的风险。因此,架构中设计了后备机制:当 SearXNG 无法访问或返回空结果时,系统会依次尝试读取本地的 JSON 数据文件,最后甚至可以使用内置的 Mock 数据。这种“主备链”的设计,确保了服务的鲁棒性,不会因为某一个环节的临时故障而导致整个服务中断。在实际运行中,我观察到 95% 以上的数据都来自 SearXNG,后备机制更像是一个“安全气囊”,平时用不到,但关键时刻能保底。
2.2 “智能查询”与“内容过滤”背后的逻辑
仅仅有强大的数据源还不够,如何“问对问题”和“剔除杂质”同样关键。项目在这两点上做了细致的设计。
智能查询体现在对userInterests列表的处理上。它并不是简单地将中文关键词扔给搜索引擎。代码内部会尝试将中文兴趣词翻译成英文(或保留中英文混合状态),生成多个查询组合。例如,你设置了[“石油”, “oil news”],它可能会生成“石油 news”、“oil news”以及它们的组合变体进行搜索。这样做的好处是能同时覆盖中文和英文世界的信息源,最大化信息获取的广度。对于关注国际动态的领域(如金融、科技),这一点尤为重要。
内容过滤则直接关系到推送质量。默认的blockedDomains列表屏蔽了如zhihu.com、baike.baidu.com等站点。这并非对这些平台的否定,而是基于一个很实际的考量:我们需要的是新闻资讯和深度分析,而不是问答社区的碎片化讨论或百科词条。知乎的回答可能很有见地,但其格式和深度并不适合作为每日摘要的素材;百度百科的内容是静态知识,而非动态资讯。通过域名屏蔽,我们能有效过滤掉大量非目标内容,让 AI 摘要的“原料”更加纯净,从而提升最终输出的信噪比。你可以根据自己领域的特点,灵活调整这个屏蔽列表。
2.3 为什么选择 OpenRouter 和 Claude Haiku 做摘要?
AI 摘要模块是整个项目的“大脑”。这里有几个关键选择值得探讨。
首先,为什么是 OpenRouter,而不是直接调用 OpenAI 或 Anthropic 的官方 API?OpenRouter 是一个聚合了众多主流大模型 API 的平台,它提供了统一的接口和计费方式。其优势在于:
- 模型可选性多:除了 Claude,你还可以轻松切换到 GPT、Gemini 等模型,方便进行效果对比和成本优化。
- 成本可能更优:OpenRouter 有时能提供比官方渠道更有竞争力的价格。
- 统一管理:对于使用多个模型的开发者,一个 API Key 和一套计费体系管理起来更简单。
其次,为什么模型默认是 Claude 3 Haiku?Haiku 是 Anthropic 家族中速度最快、成本最低的模型。对于摘要这个任务,我们并不需要模型进行复杂的逻辑推理或创意写作,核心要求是:准确理解原文主旨,并用简洁、连贯的中文进行概括。Haiku 在速度和成本上做到了极佳的平衡,非常适合这种高并发、低延迟的批处理任务。maxTokens: 120和temperature: 0.5的参数设置,也是为了控制摘要的长度和稳定性,避免生成过于冗长或天马行空的内容。
实操心得:我曾尝试将模型切换到
gpt-4o-mini进行对比。发现 Haiku 在处理技术类英文文章并生成中文摘要时,速度优势非常明显,且摘要的“干货”浓度更高。而 GPT-4o-mini 偶尔会在摘要中加入一些原文没有的、略带“评价”性质的语句。对于追求客观、简洁的资讯摘要,Haiku 的“冷静”风格更符合预期。
3. 从零开始的详细部署与配置指南
3.1 环境准备:OpenClaw 与 SearXNG
Smart Digest 是 OpenClaw 的一个 Skill,因此一个正常运行的 OpenClaw 环境是前提。假设你已经安装并配置好了 OpenClaw,并且其命令行工具openclaw可以正常使用。
另一个核心依赖是SearXNG。虽然项目提供了后备方案,但为了获得最佳体验,我强烈建议在本地或内网部署一个 SearXNG 实例。
部署 SearXNG(Docker 方式,最简单):
# 创建一个目录用于存放 SearXNG 配置和数据 mkdir ~/searxng && cd ~/searxng # 下载 docker-compose.yml 配置文件 curl -fsSL https://raw.githubusercontent.com/searxng/searxng-docker/master/docker-compose.yaml -o docker-compose.yaml # 启动 SearXNG 服务 docker-compose up -d执行后,SearXNG 服务通常会在http://localhost:8080启动。你可以打开浏览器访问这个地址,确认搜索界面正常显示。这步完成后,你的本地就有了一个强大的、隐私友好的搜索引擎,为 Smart Digest 提供数据。
3.2 一键部署与手动安装详解
项目提供了极简的一键部署命令:
curl -fsSL https://raw.githubusercontent.com/maichanks/smart-digest/main/deploy.js -o deploy.js && node deploy.js这个脚本会自动完成克隆仓库、安装依赖、创建配置文件模板等操作。对于新手来说,这是最推荐的方式。
如果你想更清晰地了解每一步,或者进行定制化安装,可以遵循以下手动步骤:
定位 OpenClaw Skills 目录:OpenClaw 的技能通常存放在
~/.openclaw/workspace/skills/目录下。进入该目录。cd ~/.openclaw/workspace/skills/克隆项目:
git clone https://github.com/maichanks/smart-digest.git # 或者如果你没有 git,可以直接下载 zip 包解压到此目录安装 Node.js 依赖:
cd smart-digest npm install这一步会安装项目所需的
axios、yaml、cron等 npm 包。确保你的 Node.js 版本 >= 18。
3.3 核心配置文件config.yaml逐项精讲
配置文件是项目的控制中心,理解每一项配置的作用至关重要。下面我结合自己的使用经验,对关键配置进行解读。
smartDigest: # 你的兴趣关键词列表。这是信息获取的“种子”。 userInterests: - 人工智能 - AI agent - 大语言模型 - 特斯拉 - 新能源汽车 # 技巧:混合中英文关键词,并用更具体的词。例如用“美联储 议息会议”代替“经济”。 # 数据源配置 searchSources: searxngUrl: http://localhost:8080 # 指向你刚部署的 SearXNG 地址 maxResults: 8 # 每个兴趣词搜索返回的最大结果数。不建议设置太大,否则摘要压力大。 # categories: general # 可选:限定搜索类别,如 news, science, it 等。 # 内容过滤器 filters: blockedDomains: - zhihu.com - zhuanlan.zhihu.com - baike.baidu.com - bilibili.com # 新增:屏蔽视频站,因为摘要通常不处理视频内容 - twitter.com # 新增:屏蔽推文,信息过于碎片化 # 建议:运行几次后,观察哪些域名产出的内容质量不高,手动添加到这里。 # maxAgeDays: 2 # 可选:只保留2天内的新闻。对时效性要求高的领域(如股市)可以开启。 # 输出格式 format: grouping: by-interest # “按兴趣分组”是核心功能,让推送结构清晰。 maxItemsPerGroup: 5 # 我调整为5,避免单个兴趣点信息过多。 showSource: true # 务必保留,方便追溯原文。 showLink: true # 务必保留,这是获取全文的入口。 # AI 摘要引擎 llm: provider: openrouter openrouterApiKey: "" # 关键!建议通过环境变量设置,更安全。 model: anthropic/claude-3-haiku maxTokens: 150 # 我稍微调高了一点,让摘要更充实。 temperature: 0.3 # 我调低了,让摘要更稳定、更接近原文。 # 推送设置 channel: feishu # 可选 feishu 或 telegram target: ou_xxxxxxxxxxxxxxx # 飞书用户的 open_id 或群聊的 chat_id几个关键点的实操解释:
openrouterApiKey:永远不要将真实的 API Key 直接写在配置文件里并提交到代码仓库。最佳实践是通过环境变量设置。你可以在运行脚本前执行:export OPENROUTER_API_KEY='your-api-key-here'或者在系统的 shell 配置文件(如
~/.bashrc或~/.zshrc)中永久设置。代码会优先读取环境变量。target如何获取:- 飞书:你需要创建一个机器人,并获取机器人的
app_id和app_secret,配置到 OpenClaw 的飞书网关中。然后,在飞书群里@这个机器人,或者在私聊中发送消息,OpenClaw 的后台日志通常会打印出对应的open_id或chat_id。这是最需要耐心的一步。 - Telegram:相对简单,在 Telegram 中搜索
@userinfobot机器人,给它发送/start,它会返回你的id,这个就是target。
- 飞书:你需要创建一个机器人,并获取机器人的
userInterests设置技巧:这是决定推送质量的上游环节。不要设得太宽泛(如“科技”),要具体(如“固态电池 突破”、“Sora 视频生成”)。可以同时设置中英文,以覆盖不同来源。
3.4 测试、运行与自动化
配置完成后,不要急于设置定时任务,先进行充分测试。
预览模式测试:
node preview.js这个命令会执行完整的抓取、过滤、摘要流程,但不会真正发送消息。它会将生成的 Markdown 内容输出到控制台。这是调试配置、观察摘要效果的最安全方式。仔细检查:关键词是否匹配到相关新闻?摘要是否通顺?屏蔽域名是否生效?
单次运行测试:
node smart-digest-v2.js这次会真实地调用 OpenClaw 的消息接口进行推送。请确保你的飞书或 Telegram 客户端在线,检查是否收到消息,格式是否正确。
配置定时任务(Cron): 测试无误后,就可以让它自动工作了。使用 OpenClaw 内置的 cron 功能:
openclaw cron add --name "晚间资讯" \ --cron "0 21 * * *" \ --session isolated \ --message "cd /home/yourname/.openclaw/workspace/skills/smart-digest && node smart-digest-v2.js"--name:给任务起个名字,方便管理。--cron “0 21 * * *”:表示每天 21:00 执行。你可以根据需要调整,例如“0 9,18 * * *”表示早晚九点各一次。--session isolated:强烈建议使用此参数。这会让任务在一个独立的会话中运行,避免长时间运行的任务阻塞你与 OpenClaw 主机器人的交互。--message:需要指定技能脚本的绝对路径,或者先cd到目录再执行,确保路径正确。
使用
openclaw cron list查看所有定时任务,使用openclaw cron remove <task_id>删除任务。
4. 核心模块深度剖析与定制化改造
4.1 数据获取器(Fetcher)的工作流与容错机制
打开smart-digest-v2.js,找到数据获取部分,其逻辑是一个清晰的优先级链:
- 主源(SearXNG):对于每个兴趣关键词,构造搜索查询,向配置的
searxngUrl发送 HTTP 请求。这里使用了axios库,并设置了合理的超时(如10秒)。如果请求成功且返回了有效结果(results数组非空),则解析结果,提取标题、链接、摘要片段、来源域名等信息,进入下一步。 - 备源(本地 JSON):如果 SearXNG 请求失败(网络问题、服务未启动)或返回空结果,代码会尝试读取一个本地的
fallback.json文件。这个文件需要你手动维护,可以作为在 SearXNG 维护期间的临时数据源。你可以定期从其他渠道抓取一些数据,整理成该文件要求的格式放进去。 - 模拟数据(Mock):如果连本地 JSON 文件也不存在,则会使用内置的几组模拟数据。这确保了即使在最极端的情况下(全新环境、无网络、无本地文件),脚本也不会因数据为空而崩溃,至少能输出一个“框架”,让你知道流程是通的。
避坑指南:SearXNG 返回的结果结构可能随版本更新而变化。如果某天发现抓不到数据了,首先用浏览器访问你的 SearXNG 地址,手动搜索一个关键词,然后用浏览器的开发者工具(F12)查看网络请求的响应,确认
results数组的结构是否和代码中response.data.results的解析逻辑匹配。这是排查此类问题最快的方法。
4.2 过滤与去重(Filter & Dedup)的精细化策略
原始数据往往包含大量重复和低质信息,过滤模块是保障推送质量的关键阀门。
- URL 去重:这是最基本的。利用 JavaScript 的
Set数据结构,对所有抓取到的新闻链接进行去重,确保同一条新闻不会因为被多个搜索引擎收录而重复出现。 - 域名屏蔽:这就是配置文件中
blockedDomains发挥作用的地方。代码会检查每条结果的域名(从链接中提取),如果存在于黑名单中,则直接丢弃。我建议你定期维护这个列表。运行几天后,查看preview.js的输出,如果发现某个域名下的内容总是无关或质量低下,就把它加进去。 - 时效性过滤:如果配置了
maxAgeDays,代码会尝试从搜索结果中解析发布时间(如果 SearXNG 提供了的话),并过滤掉过于陈旧的新闻。这对于新闻资讯类摘要非常有用,但对于技术博客、深度分析类文章,可能不需要开启。
一个高级定制思路:你可以在过滤环节加入关键词白名单。例如,你只关心“特斯拉”的“自动驾驶”和“电池”相关新闻,可以在过滤时检查标题或摘要片段是否包含这些子关键词,不包含的则过滤掉。这需要你修改过滤部分的代码,增加相应的逻辑。
4.3 AI 摘要器(Summarizer)的 Prompt 工程与降级逻辑
摘要模块的核心是构造一个有效的提示词(Prompt)发给 LLM。项目的默认 Prompt 大致是:“请将以下内容总结为一句简洁的中文摘要:[原文内容]”。这个 Prompt 简单直接,对于大多数新闻类内容效果不错。
但如果你希望对摘要的风格、长度、侧重点有更多控制,可以修改代码中的 Prompt 模板。例如:
- 侧重数据:“提取以下新闻中的核心数据和事件,用一句话概括:...”
- 侧重观点:“总结这篇文章的主要观点和结论:...”
- 固定格式:“用‘事件:...;影响:...’的格式总结:...”
优雅降级是这里的一个亮点。当openrouterApiKey为空且环境变量也未设置时,代码不会报错,而是会执行fallbackToSnippet函数。这个函数会简单地截取原文内容的前 N 个字符(例如150字)作为“摘要”。虽然不如 AI 总结得精炼,但保证了最基本的信息传递功能,实现了“有 AI 更好,没 AI 也能用”的健壮性设计。
4.4 消息发送与 OpenClaw 网关集成
消息发送部分封装得很好,主要调用openclaw.message.send方法。关键点在于错误处理和超时控制。
代码中设置了一个18 秒的硬超时(hard timeout)。这是因为消息发送依赖于外部的飞书/Telegram 网关和网络,可能存在延迟或阻塞。如果不设置超时,一个卡住的消息发送请求可能会让整个 cron 任务挂起,影响后续执行。18秒是一个比较充裕且合理的值。
此外,它还实现了简单的重试机制。如果发送失败(非超时错误),会尝试重试一次。这对于应对临时的网络波动很有帮助。
重要提示:确保你的 OpenClaw 网关(特别是飞书网关)配置正确且处于活跃状态。你可以通过向 OpenClaw 机器人发送一条测试消息来验证网关是否通畅。消息发送失败,十有八九是网关配置问题。
5. 实战中遇到的典型问题与解决方案
在近一个月的使用和调试中,我遇到了不少问题,也总结了一些排查经验。下面这个表格汇总了最常见的情况:
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
运行node preview.js无输出或很快结束 | 1. SearXNG 服务未运行或地址错误。 2. 兴趣关键词太冷门,搜不到结果。 3. 网络问题导致请求失败。 | 1. 检查searxngUrl,用浏览器访问确认。2. 在 SearXNG 网页上手动搜索你的关键词,看是否有结果。 3. 将 config.yaml中searchSources的searxngUrl临时改为“”,触发后备机制,看是否有本地 JSON 或 Mock 数据输出,以确定问题是否在搜索环节。 |
| 预览有输出,但摘要全是“未提供摘要”或乱码片段 | 1. OpenRouter API Key 未设置或无效。 2. 网络无法访问 OpenRouter API。 3. 请求内容过长超出发文限制。 | 1. 执行echo $OPENROUTER_API_KEY确认环境变量已设置且正确。2. 在代码中临时加入 console.log,打印出发送给 OpenRouter 的请求内容,看是否正常。3. 检查 maxTokens设置是否过小,或原文内容是否极长被截断。 |
| 能收到推送,但内容质量差(无关、重复) | 1.userInterests设置太宽泛。2. blockedDomains未有效屏蔽低质来源。3. SearXNG 搜索结果本身质量不高。 | 1. 细化你的兴趣关键词,增加限定词。例如从“投资”改为“美联储 加息”。 2. 分析预览输出中的来源域名,将垃圾信息频出的域名加入黑名单。 3. 考虑在 SearXNG 管理界面调整搜索引擎的权重,或启用“安全搜索”过滤。 |
| 定时任务不执行 | 1. Cron 表达式写错。 2. OpenClaw 主服务未运行。 3. 脚本路径错误或权限问题。 | 1. 使用openclaw cron list确认任务已添加。可用node -e “console.log(‘test’)”这类简单命令测试 cron 是否能执行。2. 确保 openclaw主进程在运行。3. 在 --message中使用脚本的绝对路径。检查脚本是否有执行权限 (chmod +x不是必须的,因为用node执行)。 |
| 推送消息格式错乱(如 Markdown 不解析) | 飞书/Telegram 对 Markdown 语法的支持有差异。 | 检查代码中生成的消息文本。飞书和 Telegram 的 Markdown 方言略有不同。如果问题持续,可以尝试简化消息格式,减少使用复杂的嵌套列表或特殊符号。项目默认生成的 Markdown 兼容性较好,通常没问题。 |
| 脚本运行一次后进程不退出 | 可能存在未释放的资源或未处理的异步操作。 | 使用--session isolated能隔离此影响。如果手动运行发现不退出,可以检查代码中是否有未关闭的数据库连接、文件句柄,或未正确结束的定时器。对于 cron 任务,只要在超时内完成工作,即使进程稍晚退出,影响也不大。 |
一个我踩过的“坑”:最初我将 SearXNG 部署在一台内存很小的 VPS 上,当 Smart Digest 并发搜索多个关键词时,SearXNG 偶尔会因内存不足而崩溃,导致返回错误。解决方案是调整 SearXNG 的 Docker 配置,限制其内存使用,或者在config.yaml中减少maxResults,并让脚本在搜索之间增加短暂的延迟(例如用setTimeout),减轻对 SearXNG 的瞬时压力。
6. 高级玩法与扩展思路
基础功能稳定后,你可以尝试一些更有趣的定制,让这个工具更贴合你的个人工作流。
6.1 扩展数据源:集成 RSS 与 GitHub Trending
项目当前以 SearXNG 为主,但其架构是开放的,很容易集成新的数据源。
集成 RSS:你可以编写一个新的 fetcher 函数,使用rss-parser这样的 npm 包,定期抓取你收藏的独立博客或新闻网站的 RSS。然后将获取到的条目,转换成与 SearXNG 返回结果相同的格式,合并到主数据流中。这样,你就拥有了“搜索引擎+固定信源”的双重保障。
集成 GitHub Trending:如果你是开发者,关注开源动态至关重要。可以借鉴作者另一个项目openclaw-github-trending的思路,写一个模块,每天抓取 GitHub Trending(特定语言或全局),将项目名称、描述、Star 增长数作为“新闻”,经过 AI 总结后推送给你。这相当于一个定制的“每日开源精选”。
6.2 摘要后处理:情感分析与自动分类
目前摘要主要是客观总结。你可以引入简单的情感分析(例如使用预训练的 NLP 库或调用相关 API),判断新闻的情感倾向(积极/消极/中性),并在摘要前加上[利好]、[风险]等标签,这对于金融、市场类资讯尤其有用。
更进一步,可以尝试对摘要进行自动分类打标。例如,关于“特斯拉”的新闻,可以自动打上#电动车、#自动驾驶、#财报等标签。这需要你预先定义好一个标签体系,然后利用 LLM 的零样本或少样本分类能力来实现。打标后的信息在回顾和整理时会更加方便。
6.3 推送渠道扩展:微信、邮件与 Webhook
目前支持飞书和 Telegram。如果你更常用其他工具,扩展起来也不复杂。
- 微信:可以通过接入企业微信机器人(类似飞书)来实现。企业微信提供了群机器人的 Webhook API,只需将格式化好的消息发送到指定的 Webhook URL 即可。
- 邮件:使用
nodemailer库,可以将每日摘要打包成一封漂亮的 HTML 邮件,在固定时间发送到你的邮箱。这对于喜欢在桌面端处理邮件的用户是很好的补充。 - 通用 Webhook:你可以修改发送模块,使其支持向一个自定义的 Webhook 地址 POST 数据。这样,任何能接收 Webhook 的应用(如 Notion、Slack、Discord,甚至是你自己写的另一个应用)都能成为消息的接收端,灵活性极大。
6.4 持久化与回顾:构建个人资讯知识库
目前的推送是“流式”的,看完可能就忘了。一个高级的玩法是增加持久化存储。每次运行后,不仅推送,还将原始链接、标题、摘要、时间戳、分类标签存储到数据库中(如 SQLite 或轻量级的 JSON 文件)。
在此基础上,你可以搭建一个简单的本地 Web 界面,用于搜索和回顾历史摘要。甚至可以定期(比如每周日)让 AI 对你一周内收到的所有摘要进行一次“综述”,生成一份周报,帮你把握趋势。这就从一个被动接收工具,升级为了一个主动的个人资讯知识管理系统。
经过一段时间的深度使用,Smart Digest 已经成了我信息摄入体系中不可或缺的一环。它不能替代深度阅读,但完美地承担了“哨兵”和“过滤器”的角色,把我从漫无目的的信息刷屏中解放出来,每天花几分钟就能掌握关注领域的动态。它的价值不在于技术有多复杂,而在于用一组简洁的自动化脚本,切实地解决了一个高频痛点。如果你也苦于信息过载,不妨花上半小时,按照上面的指南部署一套,相信你很快就能感受到这种“科技服务于人”的愉悦感。