lesson-03

⏱ Est. reading time: 7 min Updated on 5/13/2026

3.1 JavaScript 渲染挑战

大多数现代网站的核心内容是通过 JavaScript 动态加载的,而不是嵌在 HTML 里的。这是对抗简单 HTTP 爬虫的天然屏障。

sequenceDiagram
    participant SimpleCrawler as 简单爬虫 (requests)
    participant Browser as 真实浏览器 / Playwright
    participant Server as 目标服务器

    SimpleCrawler->>Server: GET /page
    Server-->>SimpleCrawler: HTML (含 
) SimpleCrawler->>SimpleCrawler: 解析 HTML... 内容为空!❌ Browser->>Server: GET /page Server-->>Browser: HTML + JS Bundle Browser->>Browser: 执行 JS,触发 API 请求 Browser->>Server: GET /api/content Server-->>Browser: JSON 数据 Browser->>Browser: 渲染完整内容 ✅

典型的 SPA(单页应用)陷阱

import requests
from bs4 import BeautifulSoup

# ❌ 对 React/Vue 等 SPA 网站完全无效
response = requests.get('https://example-spa.com/articles')
soup = BeautifulSoup(response.text, 'html.parser')
articles = soup.find_all('article')
print(len(articles))  # 输出: 0 —— 因为内容还没渲染

3.2 Cloudflare Bot Management

Cloudflare 是全球最广泛使用的 WAF/CDN,其 Bot Management 系统是目前最难绕过的反爬系统之一。

Cloudflare 的五层检测体系

graph LR
    A[请求到达 CF 边缘] --> B[L1: IP 信誉检查]
    B --> C[L2: TLS 指纹 JA3/JA4]
    C --> D[L3: HTTP 头部顺序分析]
    D --> E[L4: JavaScript 质询]
    E --> F[L5: 行为生物特征]
    F --> G{Bot Score}
    G -->|Score < 30| H[✅ 正常通过]
    G -->|30-70| I[⚠️ CAPTCHA 验证]
    G -->|Score > 70| J[🚫 直接封锁]

Cloudflare Turnstile(取代 reCAPTCHA)

Cloudflare 在 2022 年推出了 Turnstile,它在后台静默运行,无需用户点击图片。但它会执行一系列 JavaScript 检测:

// Turnstile 内部执行的部分检测(简化版)
const checks = {
  // 检测 navigator 属性是否真实
  webdriver: navigator.webdriver,           // 自动化浏览器会返回 true
  // 检测插件列表(真实浏览器有很多插件)
  plugins: navigator.plugins.length === 0,  // 无头浏览器通常为 0
  // 检测屏幕分辨率
  screen: screen.width === 0 || screen.height === 0,
  // 检测时区与语言是否匹配
  timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
};

3.3 行为生物特征分析

这是最高级的反爬手段,通过记录鼠标轨迹、键盘节奏、滚动行为来判断是否为人类:

行为特征 机器行为 人类行为
鼠标移动 直线或折线,完美精确 贝塞尔曲线,有抖动
点击间隔 固定 ms(如总是 100ms) 不规律,有时快有时慢
滚动行为 匀速,固定步长 惯性滚动,有停顿
页面停留时间 极短(抓取完立即离开) 一般 30s 以上
鼠标悬停 直接点击,不悬停 先悬停再点击

3.4 蜜罐链接(Honeypot Traps)

网站在 HTML 中隐藏了对人类不可见的链接,机器人会抓取并访问,从而暴露自己:

<!-- 蜜罐链接:CSS 将其隐藏,人类看不到也不会点击 -->
<a href="/trap-page" style="display:none; visibility:hidden">
  Click here for more info
</a>

<!-- 或者用 CSS 类隐藏 -->
<a href="/honeypot" class="hidden-link">Do not click</a>
# ✅ 防蜜罐:在爬取前过滤掉隐藏元素
from bs4 import BeautifulSoup

def get_visible_links(html):
    soup = BeautifulSoup(html, 'html.parser')
    links = []
    for a in soup.find_all('a', href=True):
        # 检查是否被 CSS 隐藏
        style = a.get('style', '')
        if 'display:none' in style or 'visibility:hidden' in style:
            continue
        # 检查是否有隐藏类
        classes = a.get('class', [])
        if any('hidden' in c.lower() for c in classes):
            continue
        links.append(a['href'])
    return links

3.5 课后问题

  1. 什么是 Cloudflare Bot Score?它如何影响请求的处理方式?
  2. 为什么使用 Selenium/Puppeteer 有时也会被检测到?
  3. 蜜罐链接如何工作?如何在爬虫中规避它?