程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Python 基础

    • Python基础
  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip包管理工具
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
前端 (opens new window)
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Python 基础

    • Python基础
  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip包管理工具
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
前端 (opens new window)
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Python 基础

  • Python 进阶

  • Python爬虫

    • requests 库 - HTTP for Humans
    • Beautiful Soup - HTML解析利器
    • Selenium - 动态网页抓取神器
      • 1. 环境准备:安装 Selenium 与浏览器驱动
        • 1.1 安装 Selenium 库
        • 1.2 安装浏览器驱动
        • 第一步:检查你的浏览器版本
        • 第二步:获取对应的 WebDriver
        • 第三步:放置 WebDriver 文件
      • 2. Selenium 基础操作
        • 2.1 启动浏览器并访问页面
        • 2.2 定位页面元素
      • 3. 与页面元素交互
        • 模拟搜索操作
      • 4. 等待!处理动态加载的关键
        • 4.1 隐式等待 (Implicit Wait)
        • 4.2 显式等待 (Explicit Wait) - 最佳实践
      • 5. 高级操作
        • 5.1 获取页面源代码和 Cookies
        • 5.2 执行 JavaScript 脚本
        • 5.3 无头模式 (Headless Mode)
    • Scrapy - 工业级爬虫框架
  • Scrapy 爬虫框架

  • Python
  • Python爬虫
scholar
2025-07-21
目录

Selenium - 动态网页抓取神器

# Selenium - 动态网页抓取神器

当我们面对那些通过 JavaScript 动态加载内容(例如,无限滚动、点击加载更多)的现代网站时,requests 库就显得力不从心了,因为它只能获取到初始的 HTML 源码。为了抓取“所见即所得”的最终页面内容,我们需要 Selenium。

Selenium 是一个 Web 应用程序的自动化测试框架,但它在爬虫领域被广泛用于模拟真实用户操作浏览器。它可以驱动浏览器执行点击、滚动、输入等各种操作,并获取到经过 JavaScript 渲染后的最终网页源代码。


# 1. 环境准备:安装 Selenium 与浏览器驱动

使用 Selenium 需要两样东西:

  1. selenium Python 库: 通过 pip 安装。
  2. 浏览器驱动 (WebDriver): 一个独立的可执行文件,作为 Python 脚本与浏览器之间的桥梁。

# 1.1 安装 Selenium 库

pip install selenium
1

# 1.2 安装浏览器驱动

你需要下载与你的浏览器版本完全对应的 WebDriver。这是一个至关重要的步骤,版本不匹配是导致 Selenium 无法启动的最常见原因。

核心原则:WebDriver 的主版本号必须与你的浏览器主版本号一致。 例如,如果你的 Chrome 版本是 125.0.6422.113,你就必须使用 125.0.6422.xx 版本的 ChromeDriver。

# 第一步:检查你的浏览器版本

  • Chrome: 在地址栏输入 chrome://version 并回车。
  • Edge: 在地址栏输入 edge://version 并回车。
  • Firefox: 在菜单中选择 “帮助” -> “关于 Firefox”。

# 第二步:获取对应的 WebDriver

你有以下两个选择:

选项 A:升级浏览器(强烈推荐)

最简单的方法是确保你的浏览器是最新版本。通常浏览器会自动更新。手动检查更新后,你只需要下载最新的稳定版 WebDriver 即可。

选项 B:寻找匹配的历史版本(当无法升级浏览器时)

如果你的浏览器版本较旧(例如你的版本是 135.0.7049.42),而官网只显示最新的 138.x 版本,你就需要去官方提供的历史版本库中寻找。

  1. 访问 Chrome for Testing 官方仪表板: https://googlechromelabs.github.io/chrome-for-testing/ (opens new window)

  2. 找到你的主版本号: 这个页面列出了所有可用的 ChromeDriver 版本。你需要找到与你的浏览器主版本号(比如 135)最接近的那个版本。通常,你应该寻找版本号等于或略低于你浏览器完整版本号的最新一个构建版本。

  3. 下载对应的驱动: 找到版本后,复制对应平台(如 win64)的 chromedriver 的 URL 并下载。

# 第三步:放置 WebDriver 文件

下载后,解压得到 chromedriver.exe (或 geckodriver.exe)。你需要将这个文件放在一个系统可以找到的路径下。推荐两种方式:

  1. 放在 Python 脚本同级目录下:最简单,但每个项目都要复制一份。

  2. 放在 Python 解释器目录下:一劳永逸。将驱动文件(如 chromedriver.exe)复制到你的 Python 安装路径的 Scripts 文件夹下(例如 C:\Python39\Scripts)。

    Windwos: py -0p 查看Python路径


# 2. Selenium 基础操作

# 2.1 启动浏览器并访问页面

from selenium import webdriver
import time

# 1. 创建一个 WebDriver 实例,这里以 Chrome 为例
#    这会自动打开一个新的 Chrome 浏览器窗口
driver = webdriver.Chrome()

# 2. 使用 .get() 方法访问一个 URL
driver.get("https://www.baidu.com")

# 3. 打印当前页面的标题
print(f"页面标题: {driver.title}")

# 4. 打印当前页面的 URL
print(f"当前 URL: {driver.current_url}")

# 5. 暂停 3 秒,方便我们观察
time.sleep(3)

# 6. 关闭当前浏览器窗口
driver.close()

# 7. 彻底退出 WebDriver,释放资源
driver.quit()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 2.2 定位页面元素

定位元素是所有自动化操作的第一步。Selenium 提供了多种定位策略,都通过 driver.find_element() (找一个) 和 driver.find_elements() (找所有) 方法实现,但需要配合 By 类来指定定位方式。

首先,需要导入 By 类:

from selenium.webdriver.common.by import By
1
By 定位策略 说明 适用场景
By.ID 通过元素 id 属性 ID 唯一时,最快最稳定
By.CLASS_NAME 通过元素 class 属性 按类名查找
By.NAME 通过元素 name 属性 多用于表单元素
By.TAG_NAME 通过标签名 如 div, p, a
By.LINK_TEXT 通过链接的完整文本 精确匹配链接文本
By.PARTIAL_LINK_TEXT 通过链接的部分文本 模糊匹配链接文本
By.CSS_SELECTOR 通过 CSS 选择器 功能最强大、最常用
By.XPATH 通过 XPath 表达式 功能同样强大,语法稍复杂
from selenium import webdriver
from selenium.webdriver.common.by import By
import time

driver = webdriver.Chrome()
driver.get("https://www.baidu.com")

# 1. 通过 ID 定位搜索框
search_box = driver.find_element(By.ID, "kw")
print(f"找到搜索框: {search_box.tag_name}")

# 2. 通过 NAME 定位搜索框
search_box_by_name = driver.find_element(By.NAME, "wd")
print(f"通过 name 找到: {search_box_by_name.tag_name}")

# 3. 通过 CSS SELECTOR 定位“百度一下”按钮
#    这是最推荐的方式
submit_button = driver.find_element(By.CSS_SELECTOR, "#su")
print(f"找到提交按钮: {submit_button.get_attribute('value')}") # 获取按钮的 value 属性

# 4. 查找所有的 a 标签 (find_elements 返回一个列表)
all_links = driver.find_elements(By.TAG_NAME, "a")
print(f"页面上共有 {len(all_links)} 个链接")

time.sleep(2)
driver.quit()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 3. 与页面元素交互

找到元素后,我们就可以模拟用户的各种操作了。

  • .click(): 点击元素。
  • .send_keys(text): 在输入框中输入文本。
  • .clear(): 清空输入框的文本。
  • .submit(): 提交表单(不常用,通常直接点击提交按钮)。

# 模拟搜索操作

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

driver = webdriver.Chrome()
driver.get("https://www.baidu.com")

# 1. 定位到搜索框
search_box = driver.find_element(By.ID, "kw")

# 2. 在搜索框中输入文字
search_box.send_keys("Python Selenium")
time.sleep(2)

# 3. 定位到“百度一下”按钮并点击
submit_button = driver.find_element(By.ID, "su")
submit_button.click()

# 4. 等待页面加载,观察结果
time.sleep(5)

print(f"搜索结果页标题: {driver.title}")
driver.quit()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 4. 等待!处理动态加载的关键

现代网站大量使用 AJAX 技术,在你访问页面后,内容可能还在加载中。如果你的 find_element 代码执行得太快,元素还没出现,就会抛出 NoSuchElementException 异常。

绝对不要使用 time.sleep() 作为主要的等待方式! 它不智能,要么等待时间太长浪费时间,要么时间太短元素还没加载出来。

Selenium 提供了两种更智能的等待机制:隐式等待和显式等待。

# 4.1 隐式等待 (Implicit Wait)

隐式等待是一个全局设置。一旦设置,WebDriver 在执行任何 find_element 操作时,如果第一时间没找到元素,它会在指定的时间内(例如10秒)反复轮询查找,直到找到元素或超时为止。

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()

# 设置一个全局的隐式等待,最长等待 10 秒
driver.implicitly_wait(10)

driver.get("https://www.some-slow-website.com")

# 现在,当执行 find_element 时,如果元素没立即出现,
# driver 会自动等待最多 10 秒。
# 这使得代码看起来很清爽,无需到处写 wait。
my_element = driver.find_element(By.ID, "some_dynamic_element")
1
2
3
4
5
6
7
8
9
10
11
12
13
14

优点:设置一次,全局生效,代码简洁。 缺点:不够灵活,只能用于等待“元素出现”,无法等待更复杂的条件(如“元素可点击”)。

# 4.2 显式等待 (Explicit Wait) - 最佳实践

显式等待是针对特定元素的、更灵活、更精确的等待方式。它让你等待某个特定条件发生后,再继续执行后续代码。这是最被推荐的等待策略。

你需要导入:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
1
2

WebDriverWait 结合 expected_conditions (EC) 提供了丰富的等待条件:

  • EC.presence_of_element_located(locator): 等待元素出现在 DOM 中。
  • EC.visibility_of_element_located(locator): 等待元素在页面上可见。
  • EC.element_to_be_clickable(locator): 等待元素可被点击。
  • ... 等等
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

driver = webdriver.Chrome()
driver.get("https://www.taobao.com")

try:
    # 1. 创建一个 WebDriverWait 对象
    #    参数:driver, 最长等待时间 (秒)
    wait = WebDriverWait(driver, 10)

    # 2. 定义你要等待的条件
    #    这里我们等待 id='q' 的搜索框变得“可被定位到”
    #    注意:locator 是一个元组 (By.ID, 'q')
    locator = (By.ID, 'q')
    search_input = wait.until(EC.presence_of_element_located(locator))
    
    # 3. 等待成功后,再执行操作
    search_input.send_keys("笔记本电脑")

    # 4. 等待搜索按钮“可被点击”
    search_button_locator = (By.CSS_SELECTOR, ".btn-search")
    search_button = wait.until(EC.element_to_be_clickable(search_button_locator))
    search_button.click()
    
    print("操作成功!")

except Exception as e:
    print(f"操作失败: {e}")

finally:
    time.sleep(5)
    driver.quit()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

结论: 优先使用显式等待。它让你的代码更稳定、更可靠,能精确控制等待的条件和时机。


# 5. 高级操作

# 5.1 获取页面源代码和 Cookies

  • driver.page_source: 获取经过浏览器渲染后的完整 HTML 源代码。这是 Selenium 对比 requests 的核心优势。你可以将它交给 Beautiful Soup 解析。
  • driver.get_cookies(): 获取当前站点的所有 Cookies,返回一个字典列表。
# ... 接上一个淘宝搜索的例子
from bs4 import BeautifulSoup

# 获取渲染后的页面源代码
html = driver.page_source

# 交给 Beautiful Soup 解析
soup = BeautifulSoup(html, 'lxml')
# 现在你可以用 soup.select() 等方法为所欲为了

# 获取 cookies
cookies = driver.get_cookies()
print(f"获取到的 Cookies: {cookies}")
1
2
3
4
5
6
7
8
9
10
11
12
13

# 5.2 执行 JavaScript 脚本

Selenium 允许你直接在当前页面执行任意的 JavaScript 代码,这在处理某些特殊场景时非常有用,比如滚动页面。

  • driver.execute_script(script, *args)
# ...

# 1. 将页面滚动到底部
#    这常用于触发“无限滚动”加载更多内容
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(3)

# 2. 你还可以用 JS 来直接操作元素,例如点击
#    这有时可以绕过一些对 .click() 的监听
button_to_click = driver.find_element(By.ID, "some_button")
driver.execute_script("arguments[0].click();", button_to_click)

1
2
3
4
5
6
7
8
9
10
11
12

# 5.3 无头模式 (Headless Mode)

在开发和调试时,我们希望看到浏览器窗口。但在部署到服务器上时,我们不需要图形界面。Selenium 支持在“无头模式”下运行,即在后台运行浏览器,不显示窗口。

from selenium.webdriver.chrome.options import Options

# 1. 创建一个 Options 对象
chrome_options = Options()

# 2. 添加无头模式参数
chrome_options.add_argument("--headless")
chrome_options.add_argument("--disable-gpu") # 在某些系统上需要

# 3. 在创建 driver 时传入这个 options
driver = webdriver.Chrome(options=chrome_options)

# 后续操作完全一样,只是你看不到浏览器界面了
driver.get("https://www.python.org")
print(driver.title)
driver.quit()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

掌握了 Selenium,你就拥有了应对几乎所有类型网站的终极爬虫能力。虽然它的运行速度比 requests 慢,资源消耗也更大,但在处理动态内容时,它是不可或缺的。

最佳实践: 将 requests 和 Selenium 结合使用。对于静态页面或 API 接口,使用高效的 requests;仅在需要处理动态加载、模拟登录等复杂场景时,才动用 Selenium。

编辑此页 (opens new window)
上次更新: 2025/07/25, 08:02:48
Beautiful Soup - HTML解析利器
Scrapy - 工业级爬虫框架

← Beautiful Soup - HTML解析利器 Scrapy - 工业级爬虫框架→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式