不再每天打开同一个网页:用 changedetection.io 监控价格、公告和更新日志

部署 changedetection.io,选择普通抓取或浏览器抓取,设置目标区域、降噪规则和通知,监控价格、公告与文档变化。

·9 minOpen Source
把应用部署到土耳其|BRNCHOST · 土耳其 VDS
云服务器,积分可续期|雨云 · 国内外节点 · 积分兑换权益
低价年付,大流量 VPS|RackNerd · SSD 存储 · 1Gbps 端口
香港轻量,搭个小站|晚安云 · 香港云服务器
香港 VPS,大带宽可选|野草云 · BGP 直连
大陆访问,精品线路|搬瓦工 · CN2 GIA / CTGNet 套餐
资料归档,交给 AI 整理|WorkBuddy · 本地文件处理
建站起步,先看应用镜像|腾讯云 · 轻量应用服务器
CN2 GIA,中国方向优化|DMIT · Premium 网络
双 ISP 原生住宅 IP|丽萨主机 · 美国 9929 精品线路
高频 CPU,多地部署|Evoxt · 云服务器 · 每周异地备份
京东云轻量云主机:129元/年,新人专享,限购1台

有些网页只需要偶尔打开,却不能一直忘记。软件发布了新版本,活动报名增加了名额,服务商调整了套餐,项目公告换了维护时间。手动收藏只能保住地址,不能提醒你内容已经变化。

changedetection.io 可以定期读取页面,保存比较结果,再把变化发到通知渠道。真正决定它好不好用的,是监控范围:整页比较常被日期、广告和推荐内容干扰;只截取一块又可能漏掉重要条件。开始时只做几项有明确用途的监控,比一次导入几百个网址更容易调准。

先想好收到通知后要做什么

监控价格时,通知应帮助你判断是否值得购买;监控项目公告时,需要知道版本、时间和影响范围;监控报名页面,则要能识别报名按钮或名额状态。任务不同,保留的页面区域也不同。

价格单独变化未必有意义。月付与年付切换、税费、地域、规格、优惠资格都可能改变比较结果。选择页面区域时,应把决定价格含义的条件一起保留。对版本更新也一样,只有版本号没有发布日期与变更说明,往往还得重新打开页面找信息。

优先检查网站是否已经提供 RSS、邮件订阅或 GitHub Release。稳定的官方订阅通常比抓取页面更省维护。网页监控更适合没有订阅入口,或者只关心页面某个局部的情况。

从普通网页抓取开始部署

下面是基于 官方 Compose缩减的试运行配置。需要已有 Docker 和 Compose,并为数据准备独立目录。示例采用默认镜像标签便于开始;正式长期运行前,应核对可用版本,固定镜像标签或摘要。

services:
  changedetection:
    image: ghcr.io/dgtlmoon/changedetection.io
    ports:
      - "127.0.0.1:5000:5000"
    volumes:
      - ./datastore:/datastore
    environment:
      TZ: Asia/Shanghai
    restart: unless-stopped

保存为 compose.yaml,在同一目录运行:

mkdir -p datastore
docker compose config --quiet
docker compose up -d
docker compose logs --tail=80 changedetection

服务器只监听回环地址,通过 SSH 转发查看:

ssh -L 15000:127.0.0.1:5000 user@your-server

打开本机 http://127.0.0.1:15000。macOS 上本机 5000 端口可能与其他服务冲突,用 15000 作为转发端口可以避开常见占用。

如果以后通过域名访问,再设置 HTTPS、访问认证与正确的 BASE_URL。这个地址用于通知中的实例链接,不是要监控的网站地址。监控列表、历史内容和通知凭据不适合直接公开。

首次验证可以使用自己控制的测试页面。先让正文写“报名未开放”,抓取一次;随后改为“报名已开放”,再运行检查。这样可以确认差异和通知链路,避免拿经常变化的新闻首页判断安装是否正常。

页面能打开,为什么抓不到正文

普通 HTTP 抓取读取服务器返回的内容,不会像浏览器一样执行页面 JavaScript。一些网页把主要内容交给前端请求后才渲染,抓取结果可能只剩标题和加载提示。这时先查看抓取到的内容,再决定是否切换浏览器方式。

浏览器抓取需要额外服务,耗费的资源也更多。当前官方示例推荐 sockpuppetbrowser,连接参数如下:

services:
  changedetection:
    environment:
      PLAYWRIGHT_DRIVER_URL: ws://browser-sockpuppet-chrome:3000
    depends_on:
      - browser-sockpuppet-chrome

  browser-sockpuppet-chrome:
    image: dgtlmoon/sockpuppetbrowser:latest
    restart: unless-stopped
    environment:
      MAX_CONCURRENT_CHROME_PROCESSES: "2"

这段是对前面配置的补充,要合并到同一个 services 下,并保留应用原有的端口与数据挂载。浏览器服务不用映射端口到公网。示例把并发控制在两份浏览器进程,适合先观察资源占用;它不是所有机器的容量建议。官方文件还列出了特定运行环境可能需要的能力设置,应按实际平台核对,不能只因启动失败就盲目扩大容器权限。

页面要求点击 cookie 提示或登录后才能显示内容时,可以研究 Browser Steps。账号要单独准备,授权范围保持在读取所需页面。登录会话失效、验证码或页面改版仍可能让抓取失败,应把这些失败看成需要处理的状态,不能把它们过滤成“没有变化”。项目说明列出了抓取与交互能力。

用选择器留下真正关心的区域

直接监控整页,容易收到页脚年份、推荐文章和访问统计带来的变化。先用可视选择器或 CSS/XPath 选择器圈出正文、价格卡片或公告列表,再查看结果。选择器选中的是当前页面结构,网站改版后可能失效。

假设页面有以下结构:

<section id="plan-basic">
  <h2>基础方案</h2>
  <p class="price">每月 30 元</p>
  <p class="conditions">年付适用,税费另计</p>
</section>

只选 .price 会丢掉条件,选 #plan-basic 更能保留比较上下文。这是演示结构,真实网站要查看实际 HTML,不要直接复制选择器期待适用于所有页面。

若一个页面包含多个同名 CSS 类,应确认匹配结果是不是多个套餐混在一起。对于公告列表,可以保留标题、发布时间和链接文本,避免把旁边滚动推荐也算进去。检查抓取预览比反复修改通知规则更直接。

忽略规则适合处理明确无意义的内容,例如每次请求都变化的时间戳。不要一口气忽略所有数字,价格、版本和库存恰好都是数字;也不要过滤“错误”“暂不可用”等词让面板看起来更安静。先定位噪声来自哪一块,再排除最小范围。

第一次成功抓取形成比较基线,没有通知通常是合理结果。改动选择器、语言或抓取方式后,应重新查看基线。否则后续差异可能只是提取方法变化,不能当成网站发布了新信息。

服务器看到的页面可能与你不同

页面可能根据地区、登录状态、语言、货币和 cookie 返回不同内容。VPS 上抓取的价格,未必就是你电脑上的价格。监控前固定所需地区与币种,并在通知里保留这些条件;不要把某个访问环境中的价格直接写成所有读者都能获得的优惠。

遇到 403、429 或挑战页,先看请求状态、截图和错误记录。减小检查频率、使用网站允许的订阅方式,往往比增加并发更有效。对于每天更新一次的公告,一两分钟抓取一次没有必要,还会让故障排查更复杂。

浏览器能打开而服务端抓取失败,还可能是 DNS、证书、代理或网络路径问题。分别确认容器能否访问目标、普通抓取是否成功、浏览器抓取是否成功。不要用关闭证书校验作为长期修复。

通知应包含差异和可操作的链接

changedetection.io 通过 Apprise 支持多种通知渠道。渠道 URL 常含令牌,截图分享前要遮住。先发送渠道测试,再用自己控制的页面制造一次实际变化;前者只能证明通知渠道能接收,后者才能证明监控任务到通知的全过程。

消息最好带上监控名称、页面地址和变化内容。名称写“某项目稳定版发布记录”,比“任务 17”方便判断。通知很多时,按用途分组,把真正需要尽快处理的变化放到独立渠道。

如果监控页面内容敏感,通知平台也会收到相应文本。不要默认发送整个抓取页面;只发送足够判断的区域,必要时由维护者登录实例查看完整差异。

重复提醒还可能来自页面在两种状态间切换。比如同一 URL 随机返回不同推荐内容,或者价格组件交替显示促销和原价。这时应检查原始历史,而不是只把提醒间隔拉长。范围选对后,通知数量通常会自然下降。

用三个监控样例检查规则是否选对

公告列表可以选包含标题和发布时间的主体区域。正常情况下,新公告出现会触发变化,页脚时间变化不会触发。网站将旧公告置顶时也可能触发,因此收到通知后看清是新增、重排还是删除,不要直接按“新公告”转发。

套餐监控应保留规格与价格的对应关系。先观察页面在未登录状态和自己所需地区下的表现,再固定监控条件。价格变低而内存也变小,不能算同一个方案降价;优惠到期后恢复原价,也应能从历史记录解释。如果页面包含多个购买周期,可以分别建立有清晰名称的监控,避免比较内容不断切换。

文档监控则适合选择一个具体章节,比如升级注意事项。只关注整篇文档标题会漏掉正文修改,比较全站导航又容易受到无关页面影响。一个章节被移除或重命名时,应重新定位目标。找不到选择器的错误不代表该章节仍旧没有变化。

每种样例都值得做一次“应当提醒”和一次“不应提醒”的验证。用自己控制的测试页修改目标文字,再只修改页脚;确认差异符合预期。验证范围越具体,后面调整忽略规则时越不容易悄悄屏蔽重要内容。

保存的不只是网址,还有历史和会话

/datastore 是持久化目录。备份前可以暂停应用,复制完整目录,再启动;备份放到独立存储。只导出网址列表不能保留差异历史、通知配置和其他状态。

docker compose stop changedetection
tar -czf changedetection-datastore.tar.gz datastore
docker compose start changedetection

这个演示在当前目录生成归档,实际使用时应指定独立备份位置,并设置受限权限。浏览器登录状态、通知令牌和页面历史都可能包含私人信息,备份应按同样的敏感程度管理。

恢复演练放到隔离实例,先关闭通知,避免旧监控重复发消息;确认任务、选择器与历史存在,再恢复抓取。升级之前保留数据快照和原镜像标识,因为回退镜像不一定能回退已经变化的数据格式。

每隔一段时间清理已经失去用途的监控。失效的活动、换了地址的公告、长期只报错的页面都会消耗资源和注意力。保留的每一项最好都能回答:它监控什么,变化后做什么,多久检查一次才合适。做到这一步,网页监控才会省下真正的工作,而不是把每天手动打开网页变成每天清空通知。