HTML嵌套与动态class、伪元素拼接、注释混淆、JS动态渲染等反爬手段需协同服务端校验:关键字段应多层随机嵌套+短哈希class、伪元素分段混入零宽字符、删lxml注释、耦合token的fetch解密+动态函数名,且服务端必须校验nonce与时间戳。

HTML标签嵌套与随机class名如何干扰XPath和CSS选择器
爬虫依赖稳定的选择器路径提取数据,而人为插入的冗余嵌套和动态class会直接破坏这种稳定性。比如把一个价格¥199改成
,XPath //span/text() 就会失效——它匹配到的是空字符串或乱序碎片。
实操建议:
- 服务端模板渲染时,对关键字段(如价格、销量)的父容器随机生成 3–5 层无语义
div或span,class 名用短哈希(如h3f9、k2m8)而非可预测序列 - 避免使用固定 class 前缀(如
price-*),否则正则class="price-\w+"仍能命中 - CSS 里不写具体 class 规则,改用属性选择器(如
[data-v="p"])配合 JS 动态注入 style,防止爬虫静态扫描 class 名 - 注意:过度嵌套会拖慢首屏渲染,建议只对核心字段做,且层级不超过 6 层
伪元素拼接文本为什么会被getComputedStyle()绕过
很多人以为用 ::before 和 ::after 拼出“¥”“199”就能防爬,但只要执行 window.getComputedStyle(el, '::before').content,内容就原形毕露。这不是漏洞,而是浏览器标准行为——伪元素内容本就属于计算样式的一部分。
实操建议:
- 别单独靠伪元素隐藏完整字段;若必须用,至少拆成 3 段以上(如单位、数字、后缀),分别由不同伪元素生成,并混入不可见 Unicode 字符(如
\u200B零宽空格)干扰字符串拼接逻辑 - 用 JS 动态设置
el.style.setProperty('--price-unit', '¥'),再在 CSS 中写content: var(--price-unit),这样getComputedStyle只能拿到变量名,拿不到值——但前提是变量由服务端注入,不能硬编码在 JS 文件里 - 测试时用 Puppeteer 执行
page.evaluate(() => getComputedStyle(document.querySelector('.price'), '::before').content)验证是否暴露
HTML注释与空格混淆对BeautifulSoup解析的实际影响
在 HTML 中大量插入随机注释(<!-- a7f2 -->)、换行、制表符,对 BeautifulSoup(html, 'html.parser') 几乎无感——它默认忽略注释和空白。但换成 lxml 解析器时,注释节点会作为 Comment 对象保留在树中,导致 soup.find_all(text=True) 返回一堆空字符串和注释内容,让文本提取逻辑崩溃。
实操建议:
- 如果后端用
lxml渲染模板,可在输出前用正则删掉注释:re.sub(r'<!--.*?-->', '', html, flags=re.DOTALL),但保留换行和缩进——这反而会让 XPath 定位更不稳定 - 对关键字段包裹的标签内插入零宽字符(如
),BeautifulSoup会将其当作普通文本节点,但人类不可见,strip()也清不掉,需额外清洗 - 避免在
<script></script>或<style></style>标签里塞混淆注释——这些标签内容本就不被 BeautifulSoup 当作结构处理,纯属浪费带宽
JS动态渲染内容如何避免被Puppeteer直接提取
Puppeteer 默认等待 networkidle0,但如果你用 setTimeout 延迟 2s 渲染价格,它照样等得到。真正难搞的是把 DOM 更新和网络请求耦合起来:比如先发一个带 token 的 fetch,成功后再用返回的加密字符串解密并插入真实价格——而这个 token 是从上个 API 响应头的 X-Temp-Key 里读的,且 30 秒过期。
实操建议:
- 不要用
document.write()或简单innerHTML = ...,改用document.createElement+appendChild分步构建,让 MutationObserver 难以一次性捕获完整文本 - 价格字段初始状态设为
aria-hidden="true",解密完成后才移除,防止 Puppeteer 的page.content()提前抓到占位符 - 服务端对每个用户 session 返回不同的 JS 加密函数名(如
window._d3k9()而非固定decrypt()),前端代码里不写死函数体,只通过eval执行服务端下发的加密片段——当然,eval有安全风险,仅限内网或强鉴权场景
真实对抗中,最易被忽略的不是技术多复杂,而是服务端是否真把校验逻辑下沉——比如价格解密函数依赖当前时间戳和服务端 nonce,而这个 nonce 每次请求都变,且验证失败直接返回 403。前端再花哨的混淆,挡不住一个直接调用接口的 curl。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











