网站变化
监控一个网页、或整个网站的内容,并在它发生变化时被告知:一个 价格或条款页面、一个文档站点、某个供应商的维护公告、一个公开 公告页面,或你自己网站在一次部署之后的状态。每一次变化都会保留 前后的文本、逐行差异,以及在浏览器可用时,每个版本的一张截图。
被比较的是每个页面的可见文本,而不是它的 HTML:脚本、样式、
注释、noscript、svg 和 template 块都会被去掉,空白会被
折叠,每个块(段落、标题、列表项、表格行)会变成一行。同一页面
的一次新构建、一个被重新排序的属性,或一个全新的防缓存资源
名称,都不会造成任何变化;一句被改写的话则会。
页面的哪一部分
Section titled “页面的哪一部分”网站的导航、页眉、页脚和侧边栏会被排除在外:它们在每个页面上
都一样,否则一个新的菜单项就会在一次检查中把每个页面都标记为已
变化。它们遵循 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/ 下的
所有内容;路径前缀可以选择另一个文件夹)。页面的发现方式:
- 通过网站的站点地图:
robots.txt宣布的那些(Sitemap:行), 或/sitemap.xml,包括站点地图索引(一层); - 如果没有,或站点地图在该文件夹下没有列出任何内容,则逐页 跟随链接,按广度优先的方式。
只会跟随同源(协议、主机和端口相同)的页面。当起始页面重定向到
同一网站的另一个主机(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>,用于拒绝机器人的网站。
检查如何进行
Section titled “检查如何进行”该监控项会像任何其他监控项一样被轮询(默认每分钟),但页面只会每 检查间隔分钟读取一次(默认 60,范围 5 到 10080)。在此期间, 轮询只会报告上次检查的状态:网站不会每分钟都被访问一次。检查会 在后台运行;同一监控项的两次检查绝不会重叠,监控项页面上的立即 检查会立刻启动一次检查。
第一次检查只会记录参照版本:每个页面都会被读取并保存,不会 报告任何内容。从那之后,对于每个页面:
| 情况 | 保留的内容 |
|---|---|
| 文本与上次相同(经过忽略行处理后) | 没有新内容;该页面被标记为已检查。 |
| 文本不同 | 一份新快照和一个已变化事件,附带新增和删除的行数。 |
| 一个从未见过、或曾经消失后又重新出现的页面 | 一份快照和一个新增页面事件。 |
| 该页面应答 404 或 410 | 一个页面已移除事件,上次的快照作为”之前”。 |
| 网站范围:一次完整爬取不再能到达某个已知页面 | 同样会产生一个页面已移除事件(“不再被链接”)。因达到最大页数或时间限制而停止的爬取,永远不会得出某个页面已消失的结论。 |
| 该页面上的任何其他错误(超时、403、子页面上的 500) | 该错误会显示在该页面上;不产生事件。 |
更改地址、范围、路径前缀、最大页数、区域或忽略行,会让下一次 检查变成一个新的参照版本,而不是把每个页面都报告为已变化(对于 调高的最大页数,则是把它新增的每个页面都报告为新增)。DumbMonit 的某次更新如果改变了读取页面的方式,也会这样做一次。
当一次检查在多个页面上发现相同的变化(删除和新增了相同的行, 例如一个横幅)时,监控项页面只会显示一次,并附上发生该变化的页面。
每次访问都会变化的行——一个时钟、一个访客计数器、“5 分钟前
更新”、一句随机引言——会在每次检查时都被报告。忽略行保存
正则表达式(Rust regex 语法),每行一个或用 | 连接;任何匹配
其中之一的文本行,在比较之前都会被去掉。例如:
Updated \d+ minutes ago|Visitors: \d+|© \d{4}起始页面不可达
Section titled “起始页面不可达”当起始页面本身无法读取时(没有应答、连接被拒绝、超时、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 次变化
会被保留;一份快照只要仍是某个页面的最新版本、或被某次保留的
变化引用,就会被保留,其余的内容(包括文件)都会在每次检查后
被删除。删除该监控项会移除全部这些内容。
监控一个网站的变化
Section titled “监控一个网站的变化”以下步骤正是表单旁边提示所展示的内容。
- 在地址中粘贴要监控的页面,带 http:// 或 https://。若要监控 整个网站或其某个部分,请粘贴其起始页面,并把”范围”设为 “网站”:同一文件夹下的每个页面都会被跟踪,直到”最大页数”。
- 每次访问都会变化的行(一个时钟、一个访客计数器、“5 分钟前 更新”)会每次都被报告:请把它们作为正则表达式列在”忽略行”中。
- 第一次检查只会记录参照版本,不会报告任何内容。从那之后, 每次检查都会逐页比较可见文本,并为每次变化保留一份前后对比, 显示在监控项页面上;“网站已变化”告警会告知你。
- 若要为每个版本生成截图,请在你的 Compose 文件中添加一个无头浏览器; 具体的配置行见文档(“高级选项”, “网站变更截图”)。 参见网站变更截图。
凭据:无。检查始终在 DumbMonit 服务器上运行:网站监控无法通过 中继代理进行。
| 选项 | 默认值 | 含义 |
|---|---|---|
范围(scope) | page | page:只监控该地址。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 主机自身提供服务的站点。 |