用「拾惠」搭建私人线报雷达

经常看到朋友发现一些活动:一份免费试用、一场品牌抽奖,或是小程序里的一次实物领取。真正让我在意的,并不只是奖品,而是同一个问题:为什么有用的信息总在不同的平台上,我看到的时候,往往已经晚了?

于是,我做了「拾惠 · 私人线报雷达」。它把网站、公开 Telegram 频道、部分品牌页面和 Bilibili 动态中的活动线索收集到一个页面,再帮我区分时效、参与条件和潜在成本。

这是这个个人博客的第一篇文章。我想完整记录它解决什么问题、怎样运行,以及现在还不能做到什么。

项目地址:discount.bismih520.com。目前是私人使用的工具,通过 Cloudflare Access 的 GitHub 登录限制访问;并非面向所有访客开放的福利平台。本篇博客公开,项目中的私人操作记录和凭据不公开。

一、我想要的,不是又一个购物推荐网站

普通优惠信息里,很多内容实际上是在鼓励消费:买满多少减多少、先充值再返、先付款再申请奖励。这些可能适合原本就有购买计划的人,却不是我最想找的东西。

拾惠首先关注三类信息:

  1. 无需消费的领取机会:满足明确条件后,可能领取食品、日用品、数字资源等。
  2. 免费参与的抽奖:品牌、创作者、平台组织的实物或其他奖品活动。
  3. 规则清楚的试用与体验:需要说明是否要交体验报告、寄回商品,或者承担运费。

这里有一个非常重要的区别:免费参与,不等于一定中奖;试用,不等于商品赠送;抓到一条信息,也不等于活动经过验证。

我的目标是减少寻找和筛选的时间。如果以后能带来实际收到的物资或节省,那才是结果。服务器运行了多久、数据库增加了多少行,都不能直接算作收益。

二、打开之后,应该怎样使用

这个项目不是把链接堆在一起就结束。我更希望每条线索都能回答几个具体问题:它是什么、在哪里、什么时候发的、我是否符合条件、接下来怎么参与。

先缩小范围,再去原文确认

页面可以按关键词、来源、分类和个人状态筛选。食品、日用品、公众号、小程序、B站等方向有对应的筛选入口。对于免费机会,系统会先做关键词判断,把疑似需要购买、充值、押金、付邮、返利任务等内容排除或标出。

筛选只是初筛,不能代替阅读规则。例如“免费送”可能藏着新用户限定、到店领取、实名要求或邮费。最终是否值得参与,仍以主办方原文为准。

把参与路径整理出来

有些线报只有一段话:“去某公众号,回复某个词,再进入某小程序。”系统会尝试从明确标注的文字里提取:

  • 公众号名称与回复关键词;
  • 小程序名称、活动口令或入口;
  • 原始活动链接;
  • 原文明确写出的参与条件。

这些字段可以直接复制,省去在摘要里来回找字。提取不到就保留空白,不凭空补一个口令。目前没有实现图片 OCR,所以只有截图、没有文字说明的活动,仍可能无法自动整理出完整步骤。

留下自己的处理状态

同一条信息可以标记为收藏、已参与或忽略。这样,下次打开不必重新判断所有旧内容。

“已参与”只是我的手动记录,不代表程序已经替我完成抽奖,也不是中奖证明。项目没有自动下单、点赞、转发、评论、关注或多账号参与功能。

三、来源很多,但不能把它们都叫「已接入」

做信息聚合最容易出现的问题,是把一个长长的来源列表误当成真实覆盖能力。我把“找到线索”“能够读取”“已经解析入库”“持续正常更新”看作不同的阶段。

截至本文整理时,主要路径如下:

来源 当前获取方式 必须说明的边界
线报网站、活动列表 读取公开列表,部分条目补充正文摘要 部分站点失效、受限或只提供检索入口
Telegram 解析公开频道预览 不读取私人聊天,不采集群成员,不代表全部频道
Bilibili 使用明确授权的登录态读取选定账号的公开动态 当前为 8 个账号的首屏,不是全站搜索或历史全量采集
微博相关品牌线索 部分公开新浪页面、转载与聚合页面 当前微博认证搜索未接通,不能称作微博全站实时抓取
豆瓣 部分公开小组列表、转载线索及检索入口 正文可见性和访问限制会影响完整度
公众号、小程序 从公开线报与订阅内容中识别活动入口 不是直接遍历所有公众号和小程序后台
小红书、抖音等 保留发现和检索线索 尚不能宣称稳定的认证采集或全量覆盖

一个带时间边界的运行快照

2026 年 10 月 10 日,在准备这篇文章时,我从实际运行的数据库读取到:

  • 147 个已配置来源条目;
  • 106 个来源的最近一次状态为正常;
  • 4,936 条已收录信息;
  • 8 个 B站授权动态来源最近检查正常。

这些数字只描述当时的系统状态,不是长期承诺,也不是实时计数器。其中包含同一网站的不同栏目、参考入口、历史信息和活动合集;147 不等于 147 个独立平台,4,936 更不等于 4,936 个正在进行、免费且可参与的抽奖。 “最近一次正常”也不自动等于“此刻仍然新鲜”。

我宁愿把这些区别写清楚,也不想用看起来很大的数字制造错觉。

四、它是怎么做出来的

现阶段,我选择了比较直接的技术组合,而不是先堆一个很重的平台:

部分 实际方案 负责什么
前端 原生 HTML、CSS、JavaScript 列表、筛选、来源状态、复制与个人标记
后端 Python + FastAPI 查询接口、权限校验、个人状态写入
存储 SQLite,使用 WAL 条目、来源映射、抓取队列和运行记录
采集 requests + BeautifulSoup,以及独立的 B站接口采集器 公开页面解析与授权动态读取
调度 systemd 服务与定时器 周期执行、防止重叠、错误后退避
入口 Cloudflare Tunnel + Access HTTPS 入口、GitHub 登录与访问限制

这不是一个装上 RSSHub 就完成的站点,也不是用 Rust 改写过的前端。RSSHub 的路由实现、社区维护的接口资料和开源采集项目提供了参考,但当前主要是一套针对实际来源编写的轻量适配器。

从来源到页面的流程

公开来源 / 经授权的动态接口
            ↓
检查是否到采集时间、是否处于错误退避
            ↓
提取标题、短摘要、原文地址、发布时间
            ↓
链接规范化、转发溯源、增量去重
            ↓
免费候选分类、参与条件提取、时效提示
            ↓
SQLite 保存条目、来源关系和队列状态
            ↓
私人网页查询、收藏、参与标记

不同来源的网页结构不同,因此适配器按来源拆开。某个网站变更结构,不应该让所有渠道一起失效。慢速正文补充也有单独队列,避免为了读完一篇长文章而延误新动态的发现。

五、「快一点」不是把所有请求都改成一秒一次

抽奖信息很看重时间,但无节制地加快请求,可能先得到限流和登录失效,而不是更多可用信息。

最初的一种低效方式是:整轮抓完,再休息固定时间。假如一轮本身很慢,真实更新间隔就会被不断拉长。现在把优先来源、常规来源和慢速补充拆开,并用每个来源的到期时间决定是否请求。

工作 当前目标 说明
选定 B站账号的新动态 每 60 秒一轮 近期连续两轮实测约 66 秒,不保证每轮都一致
高优先级品牌微博相关公开源 每 120 秒 不是微博认证搜索接口
活跃 Telegram、部分线报适配器 约每 180 秒 较慢来源保留各自间隔
网页统计与内容刷新 可见页面每 10 秒 只刷新本服务,不意味着每 10 秒抓全网

调度器唤醒频率和上游请求频率也不是一回事。例如,每 15 秒检查一次是否有任务到期,不代表每个 B站账号都每 15 秒被访问。

跨域名的公开来源可以分组并行,同一个域名内仍按顺序访问并留出间隔。B站认证接口请求至少间隔 3 秒,正文队列有数量与时间预算,后台任务有锁,防止前一轮未完成又堆上一轮。

为什么仍然可能延迟

目标一分钟,不代表从作者点击发布到我看到信息一定只要一分钟。上游缓存、接口返回延迟、网络超时、登录状态、来源自身的更新节奏,都会影响结果。

失败来源会退避:公开采集的错误退避从约 30 分钟增加到最长 6 小时;认证或限流失败会暂停相应轮次。这个策略会牺牲局部时效,但能减少持续撞击同一个错误,也避免把失效会话反复发送出去。

所以页面还需要显示最后检查时间、状态和新鲜程度。比一个永远写着“实时”的标签更重要的是:让我看见它到底多久没有成功更新了。

六、去重与时效,比继续加来源更难

同一活动可能先出现在品牌动态,再被多个博主转发,最后出现在好几个线报网站上。如果每看到一次都算一个新机会,列表会很热闹,却没有多大意义。

当前主要做了两层处理:

  1. 规范化原文链接,用稳定的链接标识去重,并保留来源映射。
  2. 对 B站转发动态尽量追到原始动态 ID 和原始发布时间,避免把转发时间当作活动开始时间。

但这还不是完整的跨平台语义去重。同一活动在微博和公众号里用了不同链接,目前仍可能是两条。不同的合集也不能直接拆成若干个“已验证抽奖”:合集只是发现入口,具体活动仍需继续解析与核验。

三种时间不能混用

  • 发布时间:原文何时发布,有可靠证据才记录。
  • 首次发现时间:采集器第一次见到这条记录的时间。
  • 截止时间:规则里明确写出的结束时间,或带不确定性的解析提示。

重新抓到一篇旧帖子,不能把它包装成今天的新活动。缺失发布时间的内容要保留不确定性,而不是直接用当前时间补齐。

日期解析也有误判风险。比如“次日公布名单”不是“今天已经结束”的充分证据。这类边界需要测试,不能只靠一个“结束”“开奖”关键词就一刀切。

七、隐私和安全:信息可以收集,凭据不能乱放

一个需要登录态的个人工具,最不应该做的事情,就是把 Cookie 放进前端、公开仓库或调试日志里。

拾惠在这些地方做了隔离:

  • 浏览器通过 Cloudflare Access 的 GitHub 登录进入,原站不提供公开管理后台。
  • 后端独立验证 Access JWT 的签名、签发者、受众和有效期,而不是只相信一个写着邮箱的请求头。
  • 上游平台凭据保存在独立的受限文件中,不随前端资源、源码仓库或普通代码备份发布。
  • 携带认证信息的采集只访问固定 HTTPS 域名和路径;不跟随任意跳转,避免将凭据带到其他站点。
  • 抓取结果按文本显示,不执行来源里的脚本;同时限制响应大小、超时和页面可加载的资源。
  • 收藏等写入操作也要通过登录与同源检查,避免第三方页面借浏览器偷偷修改状态。

HTTPS、访问控制和文件权限解决的是不同问题。它们不是一句“全部端到端加密”的替代说法,也不能让数据泄露风险归零。会话失效后仍需要重新授权,备份本身也必须控制访问。

公开文章里不会提供任何真实 Cookie、令牌或运维凭据。这个博客和线报站是两套内容边界:博客负责分享思路,线报站保留私人使用状态。

八、我如何判断它有没有真的做好

目前本地测试覆盖了价格和免费候选识别、文本提取、链接去重、登录拒绝、同源校验、个人标记、时间过滤和调度间隔等行为。最近一次提频修改运行了 42 项测试,全部通过。这是代码层面的验证,不等于每个网站永远可抓,也不能证明每条活动真实有效。

对运行中的系统,我更关心以下指标:

指标 为什么需要
来源最近成功时间与失败原因 找到坏掉的接口、过期登录和陈旧数据
每轮新增的去重条目 不把重复写入包装成增长
原文发布时间到首次发现的延迟 判断采集是否真的及时;缺失日期的不硬算
免费候选的误报率 看看是否混进了付邮、消费返利和无关促销
收藏后实际参与、收到的结果 最终衡量有没有减少时间、带来实际价值

最后三项还没有形成完整、持续的自动评估报表;特别是实际中奖、节省金额和收入,不能从抓取日志推导出来。我没有可据此承诺的稳定收益。

九、接下来值得做什么

我希望它继续变好,但不是只把来源数字翻倍。更有价值的方向是:

  1. 补齐关键渠道:在明确授权的前提下恢复微博认证采集,持续验证 B站来源;公众号和小程序仍从公开、可核验的入口逐步扩展。
  2. 更好的活动级去重:识别不同平台是否在描述同一件事,并聚合原始规则与转载来源。
  3. 图文线索识别:对只有海报的活动探索 OCR,但保留原图证据和识别不确定性。
  4. 更可靠的截止时间与条件提取:明确城市、新客、邮费、库存和体验报告要求,减少点进去才发现不适合的情况。
  5. 个人结果记录:记录是否参与、是否中奖、是否实际收到、花了多少时间,而不是把奖品标价当作收益。
  6. 低打扰的提醒:只提醒匹配个人偏好、时效明确的新活动;这仍是后续方向,不是本文所述版本已经全面上线的通知能力。

这些工作都有一个共同目标:从“收集得多”走向“信息值得看”。

十、第一篇,先从一个真正会用的工具开始

这个项目的起点很日常:我不想每天把时间消耗在来回刷平台上,又不想错过有价值的机会。

做下来才发现,真正费功夫的不是把网页抓下来,而是分辨来源有没有接通、内容是不是重复、规则是不是免费,以及页面上的数字有没有让人误解。

我希望这篇文章成为一个起点。以后记录的项目,也尽量遵循同样的方式:讲清动机,写出实际方案,留下验证结果,同时承认边界。

不是让服务器看起来很忙,而是让它帮我少做一些重复的事。


参考与延伸阅读

  • 拾惠 · 私人线报雷达:本文介绍的项目,访问需要授权。
  • RSSHub:路由与订阅采集实现参考;本项目没有宣称部署了整套 RSSHub。
  • bilibinggo:来源配置、动态读取及原始 ID 处理思路参考;未启用其自动参与行为。
  • Bilibili 动态接口资料:社区维护资料,接口可能变化,不代表平台官方稳定性承诺。
  • weibo-search:认证搜索调研参考,不代表当前已接通。
  • Cloudflare Access:访问控制相关文档。
  • Hexo 与 Icarus:这个个人博客使用的生成器和主题。

本文功能与统计以 2026 年 10 月 10 日的核验为准。来源状态会变化;活动规则请回到原文确认。

下一篇