网站更新监控平台 · 如何正确填写 CSS 选择器以抓取公告列表
CSS 选择器用来告诉监控程序:"在网页的哪个位置找到公告条目"。每条公告通常是一个链接(<a> 标签),选择器的目标就是精准定位这些链接。
| 写法示例 | 含义 | 适用场景 |
|---|---|---|
ul.doc_list li a | class=doc_list 的 ul 下的 li 里的链接 | 最常用,精确指定列表容器 |
ul.list-news li a | class=list-news 的 ul 下的链接 | 带明确 class 的列表 |
table.lm_tabe td a | 表格型布局中的链接 | 用 table 展示公告的站点 |
div.body_right ul li a | 某 div 区域内 ul 列表的链接 | 容器有 id/class 但 ul 没有 |
ul li a | 页面所有 ul 下的链接 | 页面只有一个 ul,或不在乎多抓几条 |
F12 打开浏览器开发者工具
body > div.main > ul > li:nth-child(1) > a
以下每个坑都是真实踩过的,不看完很容易填错。
body > div.body_bg > div > div.body_right > ul > li:nth-child(1) > a
只匹配第 1 条公告,其余全部漏掉!
div.body_right ul li a
匹配该 ul 下所有 li 的链接。
:nth-child(1) 或 :nth-of-type(1),必须删掉。它只代表你点的那一条,不是所有公告。
body > div.body_bg > div > div.body_right > ul > li > a
div.body_right 下可能有多个无名的 <ul>(导航、侧栏、页脚各一个),绝对路径可能命中第一个——恰好不是公告列表。
div.body_right ul li a
或者先用 Console 确认容器下有几个 ul:document.querySelectorAll('div.body_right ul').length
只有 1 个就可以放心用。
body > 开头的冗长前缀,保留最有辨识度的父容器 class/id + ul li a。如果父容器下多个 ul,用 :nth-of-type(n) 指定第几个。
有些网站的链接地址是 JavaScript 动态设置的(HTML 源码里 <a> 没有 href,页面加载后 JS 赋值)。这种情况下:
| 选择器写法 | 结果 | 原因 |
|---|---|---|
a[href*="/ywdt/wsgs/"] | 匹配到 0 条 ❌ | 原始 HTML 里没有这段 href |
a[href^="/202"] | 匹配到 0 条 ❌ | 同上,属性选择器匹配的是源码值 |
div.body_right a[href^="20"] | 匹配到 0 条 ❌ | 同上 |
div.body_right ul li a | 匹配成功 ✅ | 纯结构选择器,不看属性值 |
document.querySelectorAll('你的属性选择器').length 如果返回 0,但页面上明明有链接 → 就是 JS 动态 href。容器 ul li a),不要用属性选择器。
如果选择器太宽泛(比如用了 body ... ul li a 但命错了 ul),可能抓到:
.cls-1{fill:#fff} — SVG 图标的 CSS 样式代码javascript:void(0) — 占位链接(返回顶部、logo 等)https://xxx.com/help.html — 建站公司的装饰链接少数站点的公告列表在 <iframe> 里,或者需要等 JS 执行完才出现。这种情况下普通 HTTP 抓取拿不到内容。
以下是从安徽/江苏各地教育局/政务网实际采集的选择器,按 DOM 结构分类:
| 选择器 | 典型站点 |
|---|---|
ul.doc_list li a | 合肥各区、滁州 |
ul.list-news li a | 亳州 |
ul.xxgk_nav_list li a | 宿松、望江、怀宁、琅琊 |
ul.m-clist li a | 阜阳、颍泉、临泉、阜南 |
ul.m-liststyle li a | 颍上、太和 |
ul.m-dasheda li a | 颍州 |
ul.gszx_list li a | 阜阳人才网 |
ul.ulresult li a | 南京鼓楼/玄武/溧水/六合/建邺区政府 |
ul.ulresultSearchList li a | 南京某区(带 SearchList 后缀) |
ul.pageP1List li a | 南京某区 |
ul.ulnewlist li a | 南京某区 |
ul.list-style-con ul li a | 南京市教育局 |
div.articlelist ul li a | 南京某区(articlelist 容器) |
| 选择器 | 典型站点 |
|---|---|
ul li a | 芜湖人才网、亳州高新区、乡镇、六合教育、南京雨花台/江宁/秦淮等 |
| 选择器 | 典型站点 |
|---|---|
table td a | 和县等表格型公告页 |
table.lm_tabe td a | 南京某区(lm_tabe 样式表格) |
| 选择器 | 说明 |
|---|---|
div.body_right ul li a | div.body_right 下只有一个 ul 时 |
div.dpgl_con ul li a | 同上,不同容器名 |
div.links ul li a | 江宁区等 |
ul:nth-of-type(3) li a | 页面多个无名 ul 时,指定第 3 个 |
在「编辑监控」弹窗中填写网址和选择器后,点击 「🔍 测试选择器」 按钮,系统会实时抓取该页面并用你的选择器解析,直接展示匹配到的条目(标题 + 链接)。如果看到的是真实的公告标题就对了;如果看到 SVG 代码、空白、或无关内容就说明选择器有问题。
在目标页面按 F12 → Console,粘贴执行:
// 看匹配到多少条
document.querySelectorAll('你的选择器').length
// 看前 3 条的内容
Array.from(document.querySelectorAll('你的选择器')).slice(0,3).map(a => a.textContent.trim().slice(0,40) + ' | ' + a.href)
A:可能抓到无关内容(SVG 样式、导航链接),导致推送通知里出现乱码或垃圾信息。更糟糕的是可能什么都抓不到,监控永远显示"无变化"。
A:最常见的原因是页面由 JS 动态渲染。浏览器 Console 看到的是 JS 执行后的完整 DOM,但服务端 HTTP 请求只拿到初始 HTML。解决方案:给该监控勾选「浏览器模式」。
A:不能直接用! 必须先做两件事:①删掉 :nth-child(1);②检查绝对路径是否指向了正确的容器。详见上方「坑 #1」和「坑 #2」。
a[href*="xxx"])可以用吗?A:可以,但要确认 href 不是 JS 动态赋值的。动态 href 的页面属性选择器会返回 0 条结果。不确定的话用纯结构选择器更稳。
A:不会。系统只推送新增的条目(跟上次基准对比后的差异)。首次运行只建立基准不推送。