首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Python Selenium 动态爬虫实战:从环境搭建到反爬规避

Python Selenium 动态爬虫实战:从环境搭建到反爬规避

原创
作者头像
用户12818508
发布于 2026-11-14 10:24:57
发布于 2026-11-14 10:24:57
40
举报

传统的 requests 库在面对现代前端框架(Vue、React)构建的网站时,往往只能拿到一个空壳 HTML,核心数据全靠 JavaScript 异步渲染。Selenium 的核心价值在于驱动真实浏览器执行 JS,让 DOM 完整渲染后再提取数据,这是解决动态页面采集最直观的方案。但它的代价是资源消耗大、速度慢,且默认配置下容易被网站识别出自动化特征。本文从实战角度出发,覆盖环境配置、元素定位、等待策略与基础反检测,最后给出一个可直接运行的完整示例。


一、环境准备

Selenium 4.x 已内置驱动管理,不再需要手动下载 chromedriver 并配置环境变量,安装后即可直接使用。

bash

代码语言:javascript
复制
pip install selenium==4.15.2

浏览器建议使用 Chrome 或 Edge,版本需与本地安装的浏览器主版本匹配。Selenium 4.6+ 会自动调用 Selenium Manager 解析并下载对应驱动,省去了传统教程中手动放置驱动的步骤。


二、核心流程与代码骨架

一个完整的 Selenium 爬虫通常包含四个环节:启动浏览器 → 访问页面 → 等待目标元素 → 提取数据。下面以豆瓣电影 TOP250 为例,展示基础实现。

代码语言:javascript
复制
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

# 1. 启动浏览器(保持有头模式,无头模式更易被检测)
options = webdriver.ChromeOptions()
options.add_argument("--disable-blink-features=AutomationControlled")
driver = webdriver.Chrome(options=options)

try:
    # 2. 访问目标页面
    driver.get("https://wlt.vllzncv.com")

    # 3. 显式等待:等待电影列表容器出现(最多 10 秒)
    WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.CLASS_NAME, "grid_view"))
    )

    # 4. 提取单页数据
    items = driver.find_elements(By.CSS_SELECTOR, ".grid_view .item")
    for item in items:
        title = item.find_element(By.CSS_SELECTOR, ".title").text
        rating = item.find_element(By.CSS_SELECTOR, ".rating_num").text
        print(f"{title} —— {rating}分")

    # 5. 模拟点击“下一页”(豆瓣分页是普通链接,可直接定位后 click)
    next_btn = driver.find_element(By.CSS_SELECTOR, ".next a")
    if next_btn:
        next_btn.click()
        time.sleep(2)  # 给页面加载留出余量
        print("已翻页,当前 URL:", driver.current_url)

finally:
    driver.quit()

这段代码的关键点在于显式等待。WebDriverWait 配合 expected_conditions 会持续轮询直到元素出现或超时,比粗暴的 time.sleep(10) 更精准,也不会在网速快时白白浪费等待时间。


三、元素定位策略的选择

Selenium 支持 ID、Class、XPath、CSS Selector 等多种定位方式。实战中建议优先使用 CSS Selector,语法简洁且在现代浏览器中解析速度快;只有在需要根据文本内容匹配或处理复杂层级关系时才动用 XPath。

方式

示例

适用场景

CSS Selector

.grid_view .item .title

常规层级结构、类名稳定

XPath

//div[@class="item"]//span[1]

需要按文本匹配、父级回溯

ID

By.ID, "kw"

元素有唯一 id 时最快

Class Name

By.CLASS_NAME, "title"

单一类名匹配

豆瓣页面结构相对稳定,CSS Selector 足够应对。如果目标网站类名是动态生成的(如 class="item-a3f2b"),则需要改用结构选择器(:nth-child)或 XPath 的 contains() 函数。


四、反爬检测与基础规避

Selenium 最明显的特征之一是 navigator.webdriver 属性在自动化环境下为 true,而普通浏览器为 undefined。许多网站的反爬脚本会优先检查这一点。此外,ChromeDriver 还会在 window 作用域注入 cdc_ 开头的变量,同样可能被扫描到。

基础规避手段包括:

(1)屏蔽自动化标志

代码语言:javascript
复制
options.add_argument("--disable-blink-features=AutomationControlled")
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
    "source": "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
})

(2)使用有头模式而非无头模式

Headless Chrome 的 User-Agent 中会包含 HeadlessChrome 标识,部分网站直接据此拦截。如果服务器没有图形界面,可搭配 xvfb 虚拟显示运行有头浏览器。

(3)随机化操作间隔

固定节奏的点击和翻页本身就是异常信号。在动作之间加入 random.uniform(1, 3) 秒的随机延迟,比固定 sleep(2) 更接近真人行为。

(4)控制访问频率

无论使用什么工具,短时间内高频请求同一站点都容易触发 IP 限流或验证码。如果采集量较大,需要配合代理池轮换出口 IP,但代理质量参差不齐,建议先用低频率试跑观察响应状态。


五、常见坑点与处理

元素定位失败但页面明明有:多数情况是 iframe 嵌套。需要先 driver.switch_to.frame() 切换到目标 frame 再定位,结束后 switch_to.default_content() 切回。

点击被遮挡或抛出 ElementClickInterceptedException:常见于弹窗未关闭或元素在视口外。可先执行 driver.execute_script("arguments[0].scrollIntoView();", element) 滚动到元素位置,再用 JS 直接触发 click。

翻页后元素引用失效(StaleElementReferenceException):DOM 刷新后旧引用失效,需要重新定位。不要在循环外一次性获取所有元素引用后再翻页,每次翻页后重新查找。

页面加载慢但元素已可用:driver.get() 默认等待 load 事件,即所有图片、样式表加载完毕。对于纯数据采集,可以设置 page_load_strategy = "eager" 或 "none" 来缩短等待,配合显式等待目标元素即可。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、环境准备
  • 二、核心流程与代码骨架
  • 三、元素定位策略的选择
  • 四、反爬检测与基础规避
  • 五、常见坑点与处理
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档