📖 CSS 选择器使用教程

网站更新监控平台 · 如何正确填写 CSS 选择器以抓取公告列表

← 返回监控平台

一、什么是 CSS 选择器?

CSS 选择器用来告诉监控程序:"在网页的哪个位置找到公告条目"。每条公告通常是一个链接(<a> 标签),选择器的目标就是精准定位这些链接。

✅ 核心原则:选择器应该匹配到所有公告条目的 <a> 链接,且不要匹配到无关内容(导航、页脚、SVG 图标等)。
写法示例含义适用场景
ul.doc_list li aclass=doc_list 的 ul 下的 li 里的链接最常用,精确指定列表容器
ul.list-news li aclass=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,或不在乎多抓几条

二、标准操作流程(推荐)

  1. 打开目标网页,按 F12 打开浏览器开发者工具
  2. 在 Elements(元素)面板中,点击选中一条公告标题/链接(左上角箭头图标 → 点页面上的公告文字)
  3. 右键选中的元素 → Copy → Copy selector,得到一个类似这样的路径:
    body > div.main > ul > li:nth-child(1) > a
  4. ⚠️ 不要直接粘贴! 按下面「避雷指南」修改后再填入
  5. 填入后点编辑弹窗里的 「🔍 测试」按钮,查看实际匹配到的内容是否为公告

三、⚠️ 常见坑与避雷指南(必读!)

以下每个坑都是真实踩过的,不看完很容易填错。

坑 #1:DevTools 复制的路径带 :nth-child(1)

❌ 错误(DevTools 原始复制)
body > div.body_bg > div > div.body_right > ul > li:nth-child(1) > a

只匹配第 1 条公告,其余全部漏掉!

✅ 正确(去掉 :nth-child)
div.body_right ul li a

匹配该 ul 下所有 li 的链接。

规则:复制出来的选择器如果包含 :nth-child(1):nth-of-type(1)必须删掉。它只代表你点的那一条,不是所有公告。

坑 #2:绝对路径太长,命中了错误的容器

❌ 危险(绝对路径 + 无名 ul)
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) 指定第几个。

坑 #3:JS 动态赋值 href → 属性选择器全部失效

有些网站的链接地址是 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匹配成功 ✅纯结构选择器,不看属性值
判断方法:在浏览器 Console 执行 document.querySelectorAll('你的属性选择器').length 如果返回 0,但页面上明明有链接 → 就是 JS 动态 href。
解决:改用纯结构选择器(容器 ul li a),不要用属性选择器。

坑 #4:选择器匹配到了 SVG / 样式代码 / 占位符

如果选择器太宽泛(比如用了 body ... ul li a 但命错了 ul),可能抓到:

识别方法:推送通知里出现奇怪的样式代码或无关链接 → 选择器命中了错误元素。
解决:用更具体的容器 class 缩小范围,或用编辑弹窗的「🔍 测试」按钮预览匹配结果。

坑 #5:页面有 iframe 或 JS 延迟渲染

少数站点的公告列表在 <iframe> 里,或者需要等 JS 执行完才出现。这种情况下普通 HTTP 抓取拿不到内容。

解决:给这条监控勾选「浏览器模式」(useBrowser),系统会用 Chromium 渲染页面后再解析。

四、常见选择器模板速查

以下是从安徽/江苏各地教育局/政务网实际采集的选择器,按 DOM 结构分类:

4.1 标准 ul/li 列表(最常见)

选择器典型站点
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 容器)

4.2 简单 ul li a(页面只有一个 ul)

选择器典型站点
ul li a芜湖人才网、亳州高新区、乡镇、六合教育、南京雨花台/江宁/秦淮等

4.3 表格型布局

选择器典型站点
table td a和县等表格型公告页
table.lm_tabe td a南京某区(lm_tabe 样式表格)

4.4 特殊容器定位

选择器说明
div.body_right ul li adiv.body_right 下只有一个 ul 时
div.dpgl_con ul li a同上,不同容器名
div.links ul li a江宁区等
ul:nth-of-type(3) li a页面多个无名 ul 时,指定第 3 个

五、如何验证选择器是否正确?

方法 A:在平台内测试(推荐 ✅)

在「编辑监控」弹窗中填写网址和选择器后,点击 「🔍 测试选择器」 按钮,系统会实时抓取该页面并用你的选择器解析,直接展示匹配到的条目(标题 + 链接)。如果看到的是真实的公告标题就对了;如果看到 SVG 代码、空白、或无关内容就说明选择器有问题。

方法 B:浏览器 Console 验证

在目标页面按 F12 → Console,粘贴执行:

// 看匹配到多少条
document.querySelectorAll('你的选择器').length

// 看前 3 条的内容
Array.from(document.querySelectorAll('你的选择器')).slice(0,3).map(a => a.textContent.trim().slice(0,40) + ' | ' + a.href)
注意:Console 验证通过 ≠ 服务器端一定能抓到。如果页面是 JS 动态渲染的,浏览器 Console 能看到但服务端 HTTP 抓取可能看不到——这种情况需要勾选「浏览器模式」。

六、FAQ 常见问题

Q:选择器填错了会怎样?

A:可能抓到无关内容(SVG 样式、导航链接),导致推送通知里出现乱码或垃圾信息。更糟糕的是可能什么都抓不到,监控永远显示"无变化"。

Q:为什么 Console 里能匹配到,但监控抓不到内容?

A:最常见的原因是页面由 JS 动态渲染。浏览器 Console 看到的是 JS 执行后的完整 DOM,但服务端 HTTP 请求只拿到初始 HTML。解决方案:给该监控勾选「浏览器模式」。

Q:可以直接用 DevTools 复制的选择器吗?

A:不能直接用! 必须先做两件事:①删掉 :nth-child(1);②检查绝对路径是否指向了正确的容器。详见上方「坑 #1」和「坑 #2」。

Q:属性选择器(如 a[href*="xxx"])可以用吗?

A:可以,但要确认 href 不是 JS 动态赋值的。动态 href 的页面属性选择器会返回 0 条结果。不确定的话用纯结构选择器更稳。

Q:一条监控检测到变化后,会把所有公告都推一遍吗?

A:不会。系统只推送新增的条目(跟上次基准对比后的差异)。首次运行只建立基准不推送。

💡 最后提醒:填完选择器后一定要点「🔍 测试」预览一下匹配结果!这能避免 90% 的选择器问题。如果测试结果不对,按照上面的避雷指南逐一排查即可。