上个月接了个需求某消费品团队想实时盯住自家品牌在几大社交平台上的讨论尤其担心夜间出现负面内容没人发现。手动刷当然不现实我就用 OpenClaw 搭了一个 7×24 小时在跑的 Agent。这个 Agent 到现在稳定跑了三周平均每天处理上万条公开信息真正需要人工介入的只有几十条。这篇我就把整个搭建过程、稳定性处理和踩过的坑一次性说清楚如果你也在琢磨“XX平台出了事我要第一时间知道”这篇文章应该能帮你少走不少弯路。先说明一下这个方案里的“监测”只针对公开信息比如公开帖子、公开评论、搜索结果页不涉及任何私信、加密群组或需要绕过权限的内容。合规是底线这一点后面我会单独展开。无论你是做品牌公关、竞品分析还是想给自己的产品加一个舆情预警能力都可以按这篇文章的步骤来。我会从需求边界讲起一直讲到怎么让它稳定跑几个月不崩。1. 先想清楚你要监测的是什么边界在哪里1.1 从“监控焦虑”到“监测需求”很多人找到我说“我要监控全网”但等我追问“具体监控什么关键词”“发现了之后要做什么动作”的时候对方往往答不上来。这其实不是一个工具问题而是需求没拆解清楚。我习惯把这件事分成四层品牌层自己的品牌词、产品词、官方账号名防止负面发酵或消费者投诉没被响应。竞品层竞品的新功能发布、促销活动、用户评价变化用来做动态调整。行业层行业关键词、监管动态、热门事件用来判断趋势和借势机会。执行层监测到之后触发什么动作——通知群里、生成工单、记入报表还是自动回复。后面三层每一层的关键词策略和采集频率都不一样。品牌词可以做到分钟级竞品词可能分钟级行业词小时级就够了。如果不分轻重全都每秒跑一遍既浪费资源也容易被平台限流。1.2 合规边界只做公开数据的“聚合”不做私域“窃取”在动手写代码之前我最想强调的就是合规。很多平台在服务条款里明确写了禁止未经许可的大规模自动化采集所以我的原则非常保守只使用开放式搜索接口、公共RSS、以及页面里不需要登录就能看到的公开信息不破解任何加密参数不绕过验证码不伪造登录态控制请求频率设置 User-Agent 和合理的间隔模拟真实用户的浏览节奏数据使用上只做聚合分析不存储不必要的个人敏感信息。为什么要这么较真因为“社交监测 Agent”听起来很酷但它本质上是一个自动化数据管道。你永远不知道某个平台的接口哪天会发生什么变化一旦因为违规采集被封了账号或收到法务函前面的所有投入都白费了。所以我宁可在功能上做取舍也要保证整个方案干干净净。如果你要监测的内容属于私密群聊、需要特定权限才能看那这个工具不是为那种场景设计的也不应该这么用。我的建议是如果你做的监测可能涉及第三方隐私先把需求拿给法务或熟悉数据合规的同事过一遍再决定技术怎么落地。2. OpenClaw 的定位它是 Agent 编排器不是传统爬虫2.1 它解决的核心问题我自己早期也写过一些零散的采集脚本命令刷一下抓完存进数据库然后设一个 crontab。问题是这种脚本组合非常脆弱今天是有效的结果明天页面结构一改就抓回来一堆空数据偶尔一个异常没处理进程挂了整套链路就静默失效了。OpenClaw 给我的感觉是它把“定时抓取、解析清洗、去重过滤、存储通知、失败重试、运行监控”这些事情封装成了一个有状态的 Agent 工作流。你只需要定义任务和规则框架会负责任务的调度、状态持久化和异常恢复。它不像传统爬虫那样只解决“怎么把网页拉下来”而是解决“怎么让一条数据管道稳定地长期运转”。这就好比普通爬虫是给你一辆车OpenClaw 是给你一套带司机的车队管理系统——不仅要跑得快还要知道什么时候加油、什么时候保养、哪辆车坏了怎么让别的车顶上。2.2 最小安装与环境准备我的安装方式很简单直接用包管理器拉起pip install openclaw如果你想从源码运行也可以拉取项目仓库后执行初始化命令git clone 你的OpenClaw版本仓库地址 cd openclaw python -m openclaw init social-monitor这里的初始化命令会生成一个social-monitor工作目录里面包含默认配置文件openclaw.yaml、任务是目录、插件目录和日志目录。装完之后跑一下自检openclaw doctor它会告诉你环境变量、Python 版本、依赖包和数据库连接是否都正常。我的经验是第一次跑doctor大概率会提示缺少 Redis 或 SQLite 驱动之类的直接补装就行。2.3 核心抽象任务、循环、管道OpenClaw 给我的体感是它把一套长期运行的 Agent 拆成三个层次任务Task一个可以被调度的最小工作单位比如“抓取某平台关键词页”“清洗上一步抓到的数据”“把高优先级内容发到群里”。循环Loop任务按周期反复执行的调度器支持 cron 表达式和固定间隔两种模式。真正要做到 7×24不是只设一个定时任务那么简单而是需要在循环里处理超时、重试和续跑。管道Pipeline多个任务按顺序连接起来前一个任务的输出作为后一个任务的输入。管道状态会持久化Agent 中途崩溃重启后可以从上次中断的位置继续跑而不是全部重来。默认的openclaw.yaml长下面这样agent: name: social-monitor timezone: Asia/Shanghai loop: tick_interval: 60 retry_interval: 300 max_retries: 5 pipeline: - name: collect type: source - name: parse type: parser - name: filter type: filter - name: store type: sink - name: notify type: messenger看起来很简单但底层已经把“每 60 秒跑一轮、失败后 300 秒重试、最多 5 次”的机制准备好了。你不需要自己写 while True 循环也不用担心 while 循环里的一个异常让整个进程退出。这个抽象是它比裸脚本稳定很多的核心原因。3. 搭建第一版关键词监测 Agent四步跑通3.1 定义监测关键词和检索规则我执行的第一个版本只盯一个场景某品牌名 产品型号的负面舆情预警。关键词我分了三种精确词例如品牌官方名称和产品全称用于召回最相关的讨论。模糊词例如常见缩写或错别字变体因为用户不会每次都打完整品牌名。组合词例如品牌名 “投诉/垃圾/避雷/退货”用逻辑与缩小检索面。关键词不是越多越好。一开始如果直接塞五十个关键词Agent 跑起来会发现数据量爆炸且噪音极大。我建议从五个以内开始跑两天看结果再逐步扩展。检索规则在 OpenClaw 里是以配置文件管理的。以自定义搜索源为例sources: - name: demo_brand_search type: search endpoint: url: https://api.example.com/search method: GET params: q: {keyword} count: 20 interval: 300interval: 300表示每 300 秒执行一次。对品牌词来说5 分钟一轮已经足够快了如果你真的到了必须秒级响应的程度那意味着监控成本会非常高而且大概率会被平台限流。3.2 写一个源适配器采集与字段标准化OpenClaw 的源适配器说白了就是告诉你“怎么接收外部数据”。它支持两种方式一种是主动拉取一种是收到 webhook 后触发。我第一版用的主动拉取因为简单。下面是我写的一个极简源适配器作用是调用搜索接口并把结果转成统一字典import hashlib import time import requests from openclaw.sources import BaseSource class DemoSearchSource(BaseSource): def __init__(self, name, endpoint, params, interval300, **kwargs): super().__init__(namename, intervalinterval, **kwargs) self.endpoint endpoint self.params params def fetch(self): session self.session_with_policy() resp session.get(self.endpoint[url], paramsself.params, timeout15) resp.raise_for_status() items resp.json().get(data, {}).get(items, []) normalized [] for it in items: link it.get(url) or it.get(link) title it.get(title) or content it.get(content) or title published it.get(publish_time) or int(time.time()) normalized.append({ source_id: hashlib.md5(link.encode(utf-8)).hexdigest(), platform: self.name, title: title, content: content, url: link, published_at: published, extra: {}, }) return normalized注意source_id我用的是 URL 的 MD5这是最基础的去重键。同一篇文章在不同平台可能 URL 不同那要靠后面的内容去重解决这里先保证同一个链接不会重复入库。还有一点session_with_policy()是 OpenClaw 提供的方法它会自动帮你带上请求间隔、重试和 User-Agent 策略。如果我自己写十有八九会忘掉请求头被平台当成机器流量。3.3 设置调度循环真·7×24 的启动姿势我最想强调的是不要用系统 crontab 直接跑这个 Agent至少不要只靠 crontab。原因有两个如果进程因为意外 OOM内存溢出挂了crontab 不会自动把它拉起来除非额外配置reboot但当时进程也不会重启。如果一次运行时间超过了 cron 的间隔会产生任务堆叠两个进程同时跑同一个任务数据重复、状态错乱。OpenClaw 自带的运行方式是我比较推荐的openclaw run social-monitor --detach--detach会让 Agent 以守护进程方式运行支持自动重启。你还可以用openclaw status social-monitor查看执行周期、上次成功时间、失败次数。我习惯每天早上一上班先看一眼状态页如果有任务失败状态页会直接标红。如果你更信任 systemd也可以把openclaw run social-monitor写进 service 文件并设置Restartalways。不过需要注意systemd 强杀进程后如果 OpenClaw 的任务状态文件没有被正常写入重启后可能会从较旧的位置续跑。为了安全我最终选择了 OpenClaw 自带的守护进程模式它会把任务游标和进度写入数据库重启后能精准续跑。3.4 接入通知结果主动来找你Agent 如果只是默默存数据那依然要人工去查价值就少了一半。我第一版直接把通知接到团队用的即时通讯机器人上实现了“高优先级的消息自动推群”。通知配置长这样messengers: - type: webhook name: team_bot url: https://example.com/hooks/your-bot-token template: | 【社交监测】发现疑似负面内容 平台{platform} 标题{title} 链接{url} 发布时间{published_at} 关键词命中{matched_keywords} filters: - type: keyword words: [投诉, 质量, 售后退款, 曝光]配置里的filters是我特别推荐加的别一上来所有内容都推送。否则你会在凌晨三点被几十条“品牌名正常讨论”的消息吵醒然后赶紧爬起来看一眼发现只是个普通用户晒单。我后来把过滤条件收紧到“命中负面词 发布 30 分钟内 互动量超过阈值”才推消息噪音一下子少了很多。4. 进阶一多源汇聚、去重和热度判断4.1 多平台字段统一跑通单一数据源之后接入第二个平台就顺理成章了。但是每个平台的返回结构都不太一样有的字段叫content有的叫desc有的叫text时间戳有的是毫秒有的是秒还有的是字符串。我的做法是在每个源适配器里把数据全部转成统一格式字段类型说明source_idstring内容唯一标识用于硬去重platformstring来源平台标识titlestring标题或首段文字contentstring正文内容authorstring作者显示名urlstring永久链接published_atinteger发布时间Unix 秒级时间戳extradict扩展字段比如点赞、评论、转发数统一字段的价值在于后续的过滤器、去重器、通知模板都可以复用同一套逻辑。我后来加了第三个数据源只写了一个新的源适配器后面所有流程一行没改。4.2 相似内容去重同一篇新闻报道会被不同账号在多个平台复制粘贴同一条微博被转来转去内容也差不多。如果不去重通知群里会出现一堆“同一件事的 N 个副本”。我用的是 OpenClaw 内置的 SimHash 去重组件实现思路很简单from openclaw.deduplicators import SimHashDeduplicator dedup SimHashDeduplicator( fields[title, content], threshold4, ) def process(item: dict) - dict: item[dedup_key] dedup.compute(item) return itemthreshold4意味着两篇内容的汉明距离小于等于 4 时判定为相同。这个值需要根据数据量调整设太小会漏重设太大可能把两篇相关但不相同的讨论误并。我调了几轮最终在品牌舆情场景下觉得 4 最合适。去重之后同一个热点事件只会保留一个代表内容进入后续提醒流程。如果你想观察事件演化可以把重复内容计数加一而不是直接丢弃。4.3 热度评分与优先级排序如果只是把负面帖子推出来那运营看到一条就要处理一条还是不够聪明。我加了一个简单的热度分让 Agent 只推送真正值得马上响应的内容。热度分公式大概长这样score log2(comments * 1.5 shares * 2 likes * 0.5 1) * time_decay_factor其中time_decay_factor按发布时间衰减规则是发布 1 小时内衰减系数为 11-6 小时降为 0.86-24 小时降为 0.524 小时以上降为 0.2。这个公式没什么高级算法但足够管用点赞转发多、发布时间又近的内容分数自然高一条三年前的旧帖即使突然有人评论时间衰减也会把它压下去。我在管道里加了一步排序pipeline: - name: score type: scorer rule: hybrid threshold: 5.0 weight: comments: 1.5 shares: 2.0 likes: 0.5只有score大于等于 5 的内容才进入通知模块。这个阈值也要看你们的处理能力团队人工响应多就调高一点响应快就可以调低。5. 进阶二长期运行的稳定性比功能更磨人5.1 内存泄漏和连接池耗尽Agent 刚跑起来的两天一切正常但到第三天OpenClaw 状态页显示内存占用从 300MB 涨到了 1.2GB再过半天直接 OOM 被系统杀掉。我排查后定位到两个常见问题源适配器里的requests.Session如果反复创建而不关闭底层连接池会越积越多通知消息模板拼接后没有清理缓存积累了大量字符串对象。解决办法也很简单不要在外面手动创建全局 Session直接用self.session_with_policy()它自己会处理连接复用和关闭另外在循环里定期调用内存回收。OpenClaw 里可以设置循环内的软重启loop: tick_interval: 60 soft_restart_interval: 86400soft_restart_interval: 86400表示每 24 小时让 worker 优雅重启一次清掉累积状态。这不影响任务游标因为游标存在数据库里重启后继续跑即可。跑了两周之后内存曲线一直很平稳。5.2 接口变更、字段缺失和解析容错社交平台的页面结构隔三差五就会改一次。如果解析逻辑太刚性比如硬编码了某个 CSS 选择器那平台一改版这个 Agent 抓回来的就是一堆空值。我的第一个版本就经历过某平台改版后返回的 JSON 里desc字段变成了abstract当时我的解析代码报KeyError任务直接失败。但因为管道有重试机制它每 5 分钟重试一次一直报了二十几次我才从日志里发现。后来我给自己定了一条规矩解析模块必须做多级兜底。def safe_get(item, keys, default): for k in keys: if item.get(k): return item[k] return default取正文时尝试多个字段名desc、abstract、text、content。取发布时间时同样做归一化处理兼容秒、毫秒和 ISO 字符串。这样平台改字段名时最多丢一些辅助信息核心链路不会挂。5.3 频率限制一定要当回事有些数据源会在同一 IP 请求次数过多时返回 429 状态码。第一次遇到时我还以为是对方故障后来看日志才发现是我们自己的请求太密了。我后来在配置文件里统一调低了采集频率policy: max_requests_per_minute: 20 backoff: initial: 2 multiplier: 2 max_backoff: 600当收到 429 或特定错误码时OpenClaw 会按指数退避策略休息从 2 秒开始翻倍到最多 10 分钟。这个策略看起来是“慢”但长期跑下来反而是最稳的。有一个反直觉的经验监测 Agent 的采集频率做到“够用就行”。品牌词 5 分钟一轮行业词 30 分钟一轮已经覆盖 99% 的场景了。你不需要秒级秒级采集只会让你更快被限制而且数据量暴增之后分析成本也跟着涨。5.4 给 Agent 本身也装上“监控”既然是 7×24 的工具那它自己也会出问题。我不可能 24 小时盯着状态页于是给 Agent 加了两层自监控心跳机制用 OpenClaw 内置的 Heartbeat每 5 分钟向一个状态数据库上报一次心跳。如果心跳超过 15 分钟没有更新我就知道 Agent 可能挂了管理后台会发出告警。日志水位每天凌晨检查日志大小和磁盘剩余空间超过阈值就自动轮转压缩。这个比想象中重要我遇到过日志文件把磁盘写满导致所有任务停摆的尴尬情况。这层“元监控”听起来像是绕圈子但非常值得做。因为你搭的 Agent 越是自动化它对运维的可见性就越重要。你不可能永远在旁边盯着它所以必须让它把“自己还活着”这件事变成一个可观测的指标。6. 写在后面投入与边界这套 Social Monitor Agent 从第一版到稳定运行前后大概花了一周。单纯写代码可能三天就够剩下四天基本都在调关键词、去重阈值、通知过滤条件和稳定性参数。如果你也打算搭一个我的建议是先别追求大而全选定一个平台 一个品牌词 一个通知群用两三天跑通再逐步加源和加规则。你会很快发现最花时间的不是 Agent 本身而是“到底什么样的内容需要通知人工”这个决策逻辑。另外OpenClaw 这类工具并不是银弹。它不会主动帮你判断一条内容是正面还是负面也不会替你处理平台接口的复杂变化。它更像是把“跑数据管道”这件事做扎实的底座让你能把精力放在数据解释和业务响应上。我现在的扩展计划是把热度评分再接一个简单的正负面词表做成轻量情感倾向判断出每周趋势报告同时把竞品词和行业词接入同一套管道让 Agent 从一个“品牌守护者”变成“行业雷达”。如果你也正在调类似的监测系统欢迎把自己的踩坑经历和经验拿出来一起聊聊很多时候别人的一条配置就能救回你一晚上的睡眠。