Skip to content

网站变化

监控一个网页、或整个网站的内容,并在它发生变化时被告知:一个 价格或条款页面、一个文档站点、某个供应商的维护公告、一个公开 公告页面,或你自己网站在一次部署之后的状态。每一次变化都会保留 前后的文本、逐行差异,以及在浏览器可用时,每个版本的一张截图。

被比较的是每个页面的可见文本,而不是它的 HTML:脚本、样式、 注释、noscript、svg 和 template 块都会被去掉,空白会被 折叠,每个块(段落、标题、列表项、表格行)会变成一行。同一页面 的一次新构建、一个被重新排序的属性,或一个全新的防缓存资源 名称,都不会造成任何变化;一句被改写的话则会。

网站的导航、页眉、页脚和侧边栏会被排除在外:它们在每个页面上 都一样,否则一个新的菜单项就会在一次检查中把每个页面都标记为已 变化。它们遵循 HTML 赋予的角色:每个 nav,不在 article、 aside、main、nav 或 section 内部的 header 或 footer (文章的页眉会保留),不在 article 和 main 内的 aside,以及 角色为 navigation、banner、contentinfo 或 search 的任何 元素。它们的链接仍会被跟随,以发现网站的页面。比较菜单、页眉 和页脚可以关闭这一行为。

监控区域把比较范围缩小到某些元素,例如 main 或 #content; 如果一个页面上找不到其中任何一个,则读取整个页面,而不是视为空。 排除区域会排除更多元素:一个 Cookie 横幅、一个”最新文章”框、 一个广告位。两者都接受用逗号分隔的简单选择器:标签(main)、 id(#content)、类(.cookie-banner)、属性([role=alert]、 [data-ad]),或它们的组合(div.notice[role=alert])。不支持后代 选择器(main p)和其他组合符。

页面(默认)只读取该监控项的地址,不做其他任何事。它也可以是 一个纯文本或 JSON 文档,逐行比较。

网站会从该地址开始,跟随同一文件夹下的每一个页面 (https://example.com/docs/intro.html 会覆盖 /docs/ 下的 所有内容;路径前缀可以选择另一个文件夹)。页面的发现方式:

  1. 通过网站的站点地图:robots.txt 宣布的那些(Sitemap: 行), 或 /sitemap.xml,包括站点地图索引(一层);
  2. 如果没有,或站点地图在该文件夹下没有列出任何内容,则逐页 跟随链接,按广度优先的方式。

只会跟随同源(协议、主机和端口相同)的页面。当起始页面重定向到 同一网站的另一个主机(example.com 到 www.example.com、http 到 https,或像 docs.example.com 这样的子域名)时,该网站被 视为位于那里,指向第一个主机的链接会在第二个主机上读取。当它 重定向到完全不同的网站(如 login.microsoftonline.com 这样的登录 页面,或第三方域名)时,不会爬取该网站:只读取起始页面,也不会 报告任何页面已被移除。指向图片、样式表、脚本、PDF、压缩包和其他 文件的链接会按其扩展名被跳过,任何非 HTML 的应答都会被忽略。 片段(#section)、跟踪参数(utm_…、fbclid、gclid 等)和空 查询会被移除,因此一个页面对应一个地址;忽略查询字符串则会 去掉整个 ?… 部分。对于以这种方式发现的页面,会 遵循 robots.txt:名为 DumbMonit 的分组,否则是 * 分组, 支持 Allow、Disallow、* 和 $。

这次爬取是有礼貌的:最多同时两个请求,两批之间间隔半秒, User-Agent 为 DumbMonit/<version>,每次请求超时 15 秒,每个 页面最多读取 5 MB。它会在达到最大页数(默认 25,最多 200) 或十分钟后停止。当爬取因最大页数而停止时,监控项页面会说明找到 了多少个页面,因此网站中未被监控的部分绝不会令人意外。用户 代理会替换 DumbMonit/<version>,用于拒绝机器人的网站。

该监控项会像任何其他监控项一样被轮询(默认每分钟),但页面只会每 检查间隔分钟读取一次(默认 60,范围 5 到 10080)。在此期间, 轮询只会报告上次检查的状态:网站不会每分钟都被访问一次。检查会 在后台运行;同一监控项的两次检查绝不会重叠,监控项页面上的立即 检查会立刻启动一次检查。

第一次检查只会记录参照版本:每个页面都会被读取并保存,不会 报告任何内容。从那之后,对于每个页面:

情况保留的内容
文本与上次相同(经过忽略行处理后)没有新内容;该页面被标记为已检查。
文本不同一份新快照和一个已变化事件,附带新增和删除的行数。
一个从未见过、或曾经消失后又重新出现的页面一份快照和一个新增页面事件。
该页面应答 404 或 410一个页面已移除事件,上次的快照作为”之前”。
网站范围:一次完整爬取不再能到达某个已知页面同样会产生一个页面已移除事件(“不再被链接”)。因达到最大页数或时间限制而停止的爬取,永远不会得出某个页面已消失的结论。
该页面上的任何其他错误(超时、403、子页面上的 500)该错误会显示在该页面上;不产生事件。

更改地址、范围、路径前缀、最大页数、区域或忽略行,会让下一次 检查变成一个新的参照版本,而不是把每个页面都报告为已变化(对于 调高的最大页数,则是把它新增的每个页面都报告为新增)。DumbMonit 的某次更新如果改变了读取页面的方式,也会这样做一次。

当一次检查在多个页面上发现相同的变化(删除和新增了相同的行, 例如一个横幅)时,监控项页面只会显示一次,并附上发生该变化的页面。

每次访问都会变化的行——一个时钟、一个访客计数器、“5 分钟前 更新”、一句随机引言——会在每次检查时都被报告。忽略行保存 正则表达式(Rust regex 语法),每行一个或用 | 连接;任何匹配 其中之一的文本行,在比较之前都会被去掉。例如:

Updated \d+ minutes ago|Visitors: \d+|© \d{4}

当起始页面本身无法读取时(没有应答、连接被拒绝、超时、HTTP 5xx),该监控项会被视为不可达:轮询失败,“监控项不可达”规则 会像对待任何监控项一样触发。此时起始页面会在每次轮询时重新尝试, 因此它的恢复会在一分钟内被发现。一个拒绝访问(401、403)的起始 页面会被报告为配置问题,而不是服务中断。该网站其他页面上的错误 只会显示在那些页面上。

只有 DumbMonit 所在主机自己能访问的地址(回环、链路本地、云端 元数据服务)会被拒绝,除非启用了允许回环和链路本地目标; 私有局域网地址始终被允许。

内置规则网站已变化(webchange_detected,信息级别)会在一次 检查发现至少一项变化(已变化、新增或已移除的页面)后触发,通知 会列出这些页面:“/pricing, /contact and 2 more”。在它处于触发状态 期间,之后每一次发现变化的检查都会再次发出通知,附上该次检查 自己的页面,即使是同样的页面;告警会在第一次没有发现新内容的 检查时解决。它始终是每个监控项一条告警,因此从告警中确认或暂停它, 也会涵盖之后的检查。它读取 dumbmonit_webchange_last_check_changes;可以像任何其他规则一样 把它关联到某个渠道,或在告警 → 规则中提高其严重级别。参见 内置规则。

指标含义
dumbmonit_webchange_pages被跟踪的页面数(不含已移除的页面)。
dumbmonit_webchange_pages_failed被跟踪、但上次读取失败的页面数。
dumbmonit_webchange_last_check_changes上次检查发现的变化数。

这些指标会在首次检查完成后出现。

DumbMonit 镜像没有浏览器:截图来自一个可选的无头 Chromium,通过 Chrome DevTools 协议驱动。在 docker-compose.yml 中把它作为 browser 服务添加到 DumbMonit 旁边,并让服务器指向它:

services:
dumbmonit:
environment:
DUMBMONIT_BROWSER_URL: http://browser:9222
browser:
image: chromedp/headless-shell:stable
shm_size: 256m
restart: unless-stopped

然后执行 docker compose up -d。没有任何东西发布浏览器的端口:只有 DumbMonit 服务器通过 Compose 网络与它通信。

DUMBMONIT_BROWSER_URL 指向该浏览器(任何以 --remote-debugging-port 启动的 Chromium,例如 chromedp/headless-shell;服务器会读取 /json/version,并连接 到该主机名解析出的地址)。

截图只会在某个页面产生新快照时拍摄(参照版本,以及每次变化), 从不在无变化的检查时拍摄:一个 1366 × 900 的窗口,完整页面最多 到 5000 像素,以 JPEG 格式保存。截图选项可以为单个监控项关闭 它。没有浏览器,或浏览器没有应答时,文本比较照常进行,快照只是 没有图片;监控项页面会说明这一点。

浏览器会像访客一样加载页面,并运行其脚本:它显示的内容可能与 DumbMonit 比较的文本(服务器发送的 HTML)不同。

每份快照的文本会保存在数据库中(每个页面最多 1 MB);截图是 /data/webchange/<device id>/ 下的文件。按监控项,最近 500 次变化 会被保留;一份快照只要仍是某个页面的最新版本、或被某次保留的 变化引用,就会被保留,其余的内容(包括文件)都会在每次检查后 被删除。删除该监控项会移除全部这些内容。

以下步骤正是表单旁边提示所展示的内容。

  1. 在地址中粘贴要监控的页面,带 http:// 或 https://。若要监控 整个网站或其某个部分,请粘贴其起始页面,并把”范围”设为 “网站”:同一文件夹下的每个页面都会被跟踪,直到”最大页数”。
  2. 每次访问都会变化的行(一个时钟、一个访客计数器、“5 分钟前 更新”)会每次都被报告:请把它们作为正则表达式列在”忽略行”中。
  3. 第一次检查只会记录参照版本,不会报告任何内容。从那之后, 每次检查都会逐页比较可见文本,并为每次变化保留一份前后对比, 显示在监控项页面上;“网站已变化”告警会告知你。
  4. 若要为每个版本生成截图,请在你的 Compose 文件中添加一个无头浏览器; 具体的配置行见文档(“高级选项”, “网站变更截图”)。 参见网站变更截图。

凭据:无。检查始终在 DumbMonit 服务器上运行:网站监控无法通过 中继代理进行。

选项默认值含义
范围(scope)pagepage:只监控该地址。site:同一文件夹下的每个页面。
最大页数(max_pages)25网站范围:每次检查最多读取的页面数,1 到 200。
路径前缀(path_prefix)该地址所在的文件夹网站范围:只监控路径以此开头的页面(/docs/)。
忽略行(ignore)——正则表达式;匹配的文本行不会被比较。
监控区域(content_selector)——简单选择器;只比较其内部的文本。
排除区域(exclude_selector)——简单选择器;其文本不会被比较。
比较菜单、页眉和页脚(keep_page_chrome)false同时比较网站的导航、页眉、页脚和侧边栏。
忽略查询字符串(ignore_query)false网站范围:仅 ?… 部分不同的地址视为同一个页面。
用户代理(user_agent)——发送它来代替 DumbMonit/<version>。
截图(screenshots)true在配置了浏览器时,为每个新版本保留一张截图。
检查间隔(check_interval_minutes)60两次检查之间的分钟数,5 到 10080。
接受无法验证的证书(insecure_tls)false用于你自己使用自签名证书的站点。
允许回环和链路本地目标(allow_private_targets)false访问由 DumbMonit 主机自身提供服务的站点。