☰
用OpenClaw打造竞赛情报助手:自动识别与智能提醒实战
2026/10/10 7:21:18 网站建设 项目流程

被竞赛通知逼疯过的人,应该都能理解我当初的起心动念。每年赛季,报名截止时间散落在十几个渠道里:有的挂在某高校官网的公告栏,有的藏在社团公众号的推文末尾,有的只在通知群里待两天就沉底。我试过用日历、用表格、用收藏夹,最后发现这些方法都治标不治本。后来我开始用 OpenClaw 搭了一个竞赛情报助手,核心能力就两件事:自动识别竞赛信息,智能提醒关键节点。它不做什么高深的事,但确实把"竞赛信息太散"这个问题彻底解决了。

这套方案适合谁?如果你跟我一样,需要同时关注多个学科竞赛,又不想雇一个人专门刷网页,那它几乎是刚需。整个搭建过程不需要写太复杂的代码,OpenClaw 提供了一套把数据源、识别规则和提醒策略串在一起的框架,我们要做的无非是把自己的需求翻译成配置和少量脚本。下面我从需求分析、识别逻辑、提醒策略和踩坑记录几个角度完整聊一遍。

1. 为什么我最终决定用一个开源助手盯竞赛信息

1.1 竞赛信息散落的真实程度

我见过最夸张的一个月,同一周内有四个比赛的截止时间需要记住。一个比赛要求报名表盖章扫描后发到指定邮箱,一个比赛在线上系统填完还要邮寄纸质材料,还有一个比赛直接说"逾期不再补报"。这些信息如果只看标题,根本分不清哪个更急。

更麻烦的是,每个信息源的更新频率完全不一样。有的官网一个月才更一次,有的公众号一天推好几条,还有的通知群只在报名前一周才有人转发。靠手工刷新网页,实际就是在赌自己的运气。我一开始用浏览器收藏夹把相关页面全部存下来,每天早上挨个点开,坚持了三天就放弃了。不是懒,而是这种操作重复性太高,任何一个页面改版或者换入口,之前的收藏就全部作废。

1.2 从"手动刷网页"到"程序盯变化"

OpenClaw 带来的最大改变,不是"自动化"这三个字,而是任务建模方式的改变。过去我盯的是"某个页面有没有出现新内容",现在让程序盯的是"页面内容是否发生了变化"。这两种思路看起来相似,实际实现路径完全不同。

人工刷新页面时,即使页面没变,你也得从头到尾扫一遍,因为你需要先确认"没有变化",然后才敢放下。程序不一样,它可以定时抓取、保存快照、对比差异,只有检测到新增内容才进入识别环节。这样一来,我每天需要做的决策从"我要不要打开这个网页"变成了"我只需要看它推过来的结果"。OpenClaw 做的事更像是把信息源变成一套可订阅的水管:水来了才会响,平时它不打扰我。

1.3 为什么叫"情报"而不叫"报名提醒"

如果只是到点了提醒一下,用手机日历就够了。真正麻烦的是,一条竞赛通知里塞了很多需要人工判断的信息:主办方是谁、参赛对象是否包含本科生、报名截止精确到几点、作品是线上提交还是发邮件、要不要交报名费、团队人数上限是多少。

这些字段放在一条公众号推文里时,要靠人肉去看、去记、去转成表格。而"竞赛情报助手"要做的,就是把这些非结构化文本变成结构化数据,再结合时间点决定什么时候提醒。所以它不是"报名提醒",而是一个轻量级情报处理流水线。OpenClaw 在其中扮演的角色,是一个能挂技能包、能定时执行、能按规则推送的执行环境。

2. 自动识别:OpenClaw 是怎么判断"这条消息值得提醒"的

2.1 先给助手配好"眼睛":数据入口设计

我实际配置的第一件事,不是识别逻辑,而是数据入口。OpenClaw 本身不生产数据,它需要我去喂源。最常见的三种入口方式我都用过:RSS 订阅、网页列表抓取、邮件转发。

RSS 是最省资源的方式,只要信息源支持,一个链接就能长期订阅。网页列表抓取则更适合那些没有 RSS 但页面结构规整的官网,配置一个 CSS 选择器,把"通知列表"里的链接抓出来即可。邮件转发用于少数只能被动接收消息的渠道,比如某些竞赛平台会把通知发到注册邮箱,我在邮箱里设置规则,把带"竞赛、大赛、报名"主题的邮件自动转发到专用收件箱,再由 OpenClaw 定时拉取。

这里有个所有人都容易忽略的点:别在一开始就追求"全量覆盖"。我刚开始想一口气接入二十个信息源,结果识别规则完全没法统一,天天误报。后来改成先接入三个最核心的来源,把整个流程跑通,再逐步加源。每一个新源都可能带来新的页面结构和措辞习惯,宁可慢慢来,也不要让整个系统因为一个不稳定的源而失控。

2.2 识别流程的三层过滤

信息源抓到原始内容后,OpenClaw 会进入识别流程。我把它拆成三层过滤,每一层解决不同的问题。

第一层是关键词命中。标题或摘要里出现"报名""竞赛""大赛""作品提交""截止日期""参赛对象"等词,先进入候选池。这一步的目的是召回,宁可多也不能少,所以阈值放得很低。

第二层是语义分类。只看关键词会有大量误报,比如"讲座通知""会议通知"里也有"截止日期"。我让 OpenClaw 把标题和正文摘要拼成一段文本,用本地模型判断它到底属于"竞赛报名""竞赛结果""活动预告"还是"普通公告"。这层过滤非常关键,它直接决定了后面会不会乱提醒。

第三层是规则校验。即使语义分类已经判断是竞赛,还要检查关键字段是否完整。至少要有比赛名称、主办单位、报名截止时间这三项,才会被判定为"可提醒的竞赛情报"。如果只有标题没有时间,宁可标记为"待补充",也不会进入提醒队列。

这三层过滤是串行执行的,前面任何一层不满足就直接丢弃,不会浪费后面大模型调用的成本。我在初期试过只靠关键词过滤,结果一天能收到十几条无关内容;加了语义分类后,误报率降了一大半;再加上字段完整性校验,整个系统才真正能安安静静地干活。

2.3 字段抽取:把自然语言变成结构化数据

识别出"这是一条竞赛通知"之后,接下来要做的是字段抽取。我主要提取这些字段:比赛名称、主办单位、报名开始时间、报名截止时间、作品提交截止时间、参赛对象、报名方式、报名入口链接、奖项设置、是否收费。

我的做法是:优先用正则和时间解析库处理固定格式,"2024年12月1日""12月1日 23:59""2024.12.01-2024.12.15"这类表述都能稳定识别。剩下无法用正则处理的,再交给语言模型做兜底抽取。OpenClaw 的优势在于它允许我把这两种方式混在一个流程里,不用自己额外搭一套调度系统。

另外,很多竞赛海报本身是图片,文字全在图上。对于这类信息源,我会在流程里加一步 OCR 识别,把海报中的文字提取出来,再走同样的字段抽取逻辑。不过 OCR 的识别结果容易有错漏,尤其是"截止"这类词经常被识别成"载止",所以 OCR 后的文本必须要经过一轮时间格式校验,解析不出来就标记为低置信度,而不是强行填一个时间。

2.4 去重与合并:防止同一场比赛被提醒五次

同一场比赛可能出现在官方通知、社团公众号和第三方汇总平台上,如果每个源都抓一遍,就会生成五条几乎相同的情报。我在 OpenClaw 里做了一层去重合并逻辑,判重指纹用"标题规范化 + 主办单位 + 链接域名"的组合来生成。

规范化标题是指把全角半角、空格、括号等字符统一,再把"2024""第四届"这类词提取成单独属性。这样就算一个信息源写成"第四届全国高校智能应用创新大赛",另一个写成"2024全国高校智能应用创新竞赛",只要主办方和 URL 域名一致,也能大概率判定为同一条比赛。

合并规则也很简单:字段优先级是"官网信息 > 公众号信息 > 汇总平台信息"。如果官网的时间已经更新,公众号那边的旧时间不会覆盖它。这个过程不需要人工参与,但每次合并都会在日志里留一条记录,方便回溯这个比赛到底是从哪个源先发现的。

3. 智能提醒:把"通知"变成"刚好提醒"

3.1 不同赛事的提醒节奏

提醒这件事,最忌讳的就是一刀切。有些比赛从发通知到报名截止只有一周,有些则长达三个月。如果所有比赛都按同一个节奏提醒,要么前期天天被无关消息打扰,要么临近截止才发现材料没准备。

我最后按比赛的生命周期拆成了三个时间点:报名开始前提醒、报名截止前提醒、作品提交截止前提醒。每个时间点又分了两档,形成一张简单的提醒节奏表:

提醒节点提前时间提醒等级内容重点
报名开始前1 天普通是否准备参赛、组队是否完成
报名截止前3 天高报名材料清单、报名入口
报名截止前6 小时紧急立即核对、是否已提交
作品提交截止前24 小时高作品格式、上传地址
作品提交截止前1 小时紧急最终检查、确认提交状态

这个节奏不是固定的,我还会根据比赛的重要程度动态调整。重要比赛会在报名开始前 3 天就提醒一次,普通比赛只在截止前 24 小时提醒。判断重要程度时,我会看主办方级别、历届规模、是否与本专业强相关,以及团队里是否已经有人点了"感兴趣"。

3.2 带上下文的提醒卡片

最初我把提醒做成了纯文本,类似"XX大赛明天截止报名"。跑了几天就发现,这种消息根本不够用。因为收到消息的时候,我通常正在处理别的事,只看到一句话根本没法决策:这个比赛我到底报名了没有?报名入口在哪?还要不要准备材料?

后来我把提醒改成上下文卡片,同时推送到 IM 机器人和邮箱。一条提醒里必须包含:比赛名称、关键时间点、剩余时间、参赛对象、报名入口、最近一次记录的报名状态、以及两个操作按钮"确认已处理"和"忽略这个比赛"。我常用的消息格式大概是这样的:

【报名即将截止】全国高校智能应用创新大赛 报名截止:2025-06-30 23:59(剩余 2 天 3 小时) 参赛对象:在校大学生,可跨校组队 报名入口:https://comp.example.edu/register 当前状态:尚未报名 操作:确认已处理 / 忽略该比赛 / 延后到明天

这条卡片里最有用的部分是"当前状态"。它是 OpenClaw 从我自己的记录表里读取的,如果我已经在某次提醒里点过"确认已处理",下一次提醒就不会再出现同一个按钮,而是会显示"已记录报名完成"。这样做避免了一个很尴尬的情况:系统提醒了三次,你每次都要回忆自己到底报没报。

3.3 多端触达和确认闭环

我一开始只把提醒推到群里,后来发现群消息极容易被刷走。然后就加了邮件,再后来加了一个待办清单。多端触达的核心不是"所有渠道都响一遍",而是给用户一个选择权:日常查看用 IM 机器人,关键截止用邮件,真正紧急的时候再把标记为紧急的消息单独置顶。

更重要的设计是"确认闭环"。每一条提醒发出去以后,OpenClaw 会把它记录为"待确认"。如果我点击了确认,状态变成已确认;如果 12 小时没有处理,系统会自动升级提醒方式,比如从普通消息变成邮件,甚至在临近截止的 6 小时把消息推到所有端。

没有这个闭环,提醒系统就只是一个单向广播器,它不知道你看到了没有,不知道你处理了没有。加了闭环之后,我能从 OpenClaw 里导出一份清单,明确看到这个赛季哪些比赛已经确认报名、哪些还悬着。这种"可追踪"比单纯的消息推送有价值得多。

4. 实测阶段踩过的四个坑

4.1 "获奖公示"差点被当成报名通知

第一个误报案例是这样的:某个比赛官网发布了一条标题为"关于公布第四届XX大赛获奖结果的通知",里面也有"竞赛""通知""名单"这些词。关键词过滤直接把它放进了候选池,语义分类也误判成了"竞赛信息",结果它就进入提醒队列,发了一条"新的报名已开放,请尽快查看"。

问题出在:它确实是一场竞赛的通知,但不是报名通知,而是赛后结果公示。我最初在语义分类里只定义了"竞赛报名"和"非竞赛",没有定义"竞赛结果公示"这个中间类别。

修复方式是在分类标签里单独加一个"竞赛结果公示"类别,并且在规则校验里把"获奖名单""公示""拟获""成绩查询""结果公布"这些词设为强排除项。只要标题或正文命中这些词,直接降权。还有一个经验:比赛名称里如果带有"结果""评审""答辩""成绩"这些词,也要警惕,这类页面通常不是报名入口。

4.2 截止时间文本的歧义比想象中严重

"11月30日前"这个表述,按字面理解是 11 月 30 日 23:59 截止,但有的人会理解成 11 月 29 日下班前。更麻烦的是"即日起至12月15日",这里没有精确到几点,我如果不加处理,就会默认解析成 12 月 15 日 00:00,直接提前了整整一天。

还有一次摔得更惨:一条通知写"报名截止到12月20日,作品提交延至12月30日",我的解析器把两个日期都当成报名截止,导致第一次提醒过早,第二次提醒又漏了作品提交这个更关键的节点。

我现在对时间解析有一个硬性要求:凡是解析出来的时间,必须保留原文摘要,并在提醒卡片里展示原句。比如提醒文案写成"按原文:截至 12 月 20 日 17:00(原文未精确到分)"。这样即使解析有偏差,用户看到的也是原始表述,可以自己判断,而不是完全信任程序给出的时间。另外,所有时间统一转成指定时区存储,避免不同服务器时区差异导致的"看起来差 8 小时"问题。

4.3 提醒太勤会变成新噪音

我在刚开始运行这套系统时,把提醒频率调得很高:报名前一天提醒一次,前半天又提醒一次,截止前 2 小时再提醒一次。三天之后我就不想再看这个机器人发的任何消息了,因为 95% 都是重复信息。

后来我加了一个"疲劳度控制"逻辑。同一个比赛在 24 小时内最多只提醒两次,除非我在操作里点了"继续提醒"。同时,如果一个比赛已经被确认过"报名完成",系统会自动取消后续所有报名相关提醒,只保留作品提交截止的提醒。

这条经验很重要:好的提醒系统不是尽量多提醒,而是在最关键的时刻出现在你眼前。为了做到这一点,我甚至主动减少了普通比赛的提醒次数,把"提醒配额"留给那些真正要赶截止时间的比赛。提醒和噪音之间只有一线之隔,这个度必须靠实际使用感受去调。

4.4 跑一段时间后进程悄悄挂了

这类定时任务最阴险的故障不是逻辑错误,而是进程不知道什么时候就停了。我遇到过 OpenClaw 的定时任务跑了半个月后不再触发,日志里没有任何报错,只是内存占用越来越高,最后被系统杀掉。还有一次是网络源因为页面改版返回 404,抓取任务连续失败,但我的逻辑里没有做失败告警,系统就静默地放弃了那个源。

现在我的稳定运行方案有三条:第一,给 OpenClaw 加一个看门狗,只要检测到超过一个抓取周期没有新任务执行,就自动重启;第二,每次抓取和识别都写结构化日志,包括耗时、命中/丢弃、触发的规则;第三,每天固定时间发一条"健康检查"消息,内容是昨天新增了几条情报、识别失败了几条、哪个源没有正常更新。如果没有这条健康检查,我根本不会发现某个信息源已经断更了一周。

5. 一份最小可用配置骨架与后续扩展思路

5.1 最小配置骨架

不同版本 OpenClaw 的字段名会有差异,我这里给出的是我实际在用的配置风格,核心逻辑都一样。如果你想照抄,请注意把 URL 和推送地址换成自己的。

sources: - name: univ_compete type: rss url: "https://comp.example.edu/feed.xml" poll_interval: "30m" - name: college_news type: webpage url: "https://www.example.edu/notice/" selector: ".notice-list a" poll_interval: "1h" recognizer: min_score: 0.6 required_fields: - competition_title - organizer - registration_deadline exclude_words: - "获奖公示" - "成绩公告" - "拟获" - "赛后总结" time_parser: timezone: "Asia/Shanghai" reminders: - at: "-1d" level: normal channel: [im] - at: "-6h" level: urgent channel: [im, email] dedup: key: ["title_normalized", "organizer", "url_host"] window: "24h"

这段配置看起来简单,但已经把最核心的行为定义清楚了:什么源要抓、多久抓一次、什么内容算有效、提醒节点在哪、重复消息怎么处理。我建议第一次跑的时候不要急着加复杂规则,先把这套最小配置跑一天,看看它识别出来的结果是否符合预期,再逐步调整。

5.2 识别脚本的写法参考

除了配置文件,我还会写少量脚本来处理 OpenClaw 自带规则不方便覆盖的场景。比如字段抽取里经常要判断"这句话里说的截止时间到底是报名还是提交作品",我写过一个很轻量的函数:

def classify_deadline(text): if any(w in text for w in ["作品提交", "作品上传", "提交作品"]): return "work_deadline" if any(w in text for w in ["报名截止", "报名于", "在线报名"]): return "registration_deadline" if any(w in text for w in ["报名和作品提交", "报名及作品提交"]): return "both_deadline" return "unknown_deadline"

这个函数解决不了所有问题,但它在大多数时候足够可靠。我的原则是,能用手写规则解决的绝不先上大模型。规则更稳定、更快、也更容易调试。只有当文本的表述形式太多样,正则实在兜不住时,我才会把这段文本交给更大规模的模型做抽取。两条路并行,比单纯依赖某一种方式更稳。

5.3 还能往哪些方向扩展

这套竞赛情报助手运行稳定之后,我顺手加了几个扩展。第一个是日历订阅:OpenClaw 会把所有识别出来的截止时间生成一个 ICS 日历文件,我把它导入手机日历,这样即使不看 IM 消息,日历上的截止事件也不会漏。

第二个是团队共享状态。在多人组队参赛时,我建了一个非常简单的状态表,记录每场比赛的"负责人""是否已报名""是否已提交"。OpenClaw 每次提醒时会附带这个状态,团队里谁还没处理一目了然。这比在群里反复问"有人报了吗"高效得多。

第三个是赛报回填。比赛公布获奖名单之后,如果列表里有我的团队成员名字,OpenClaw 会识别出来并生成一条"祝贺,你们获得了二等奖"的消息。这个功能本质上是把"识别"从报名阶段延伸到赛后阶段,让整个情报系统不再是一次性的,而是能持续记录一个赛季的完整轨迹。

5.4 给准备复刻的朋友的几条建议

最后说几条实际操作中的体会。第一条,先做减法再做加法。不要一开始就追求大而全,先接入两个信息源,把识别、提醒、确认闭环跑通,再慢慢扩。第二条,任何识别结果都要保留原始出处,否则出现误判时你根本不知道是哪个环节出了问题。第三条,提醒消息一定要带原文,特别是时间字段,别让用户对着一个被解析错误的时间做决定。

还有一点我觉得比技术更重要:整个系统的价值不是"把提醒发出去",而是"让我们敢于把竞赛信息托管给一个自动化流程"。这需要信任,而信任来自一次次准确的提醒和透明的日志。我自己用了大半个赛季之后,才真正敢不再每天去翻那几个官网。OpenClaw 给我的不是更快的通知,而是一种确信:该知道的都会知道,关键时间不会再从我眼前溜走。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询