第13课:网页爬虫|Selenium【让浏览器变成你的“自动操作机器人”】
Selenium 是一个强大的自动化测试工具,常用于网页爬虫开发,能够模拟用户操作浏览器,实现动态网页数据的抓取。通过 Selenium,可以控制浏览器执行点击、输入、滚动等操作,适用于处理 JavaScript 动态加载的网页内容。该工具支持多种浏览器(如 Chrome、Firefox),并提供了丰富的 API 进行元素定位和交互。结合 WebDriver,开发者可以编写脚本自动完成表单提交、数

文章目录
-
- 学习目标
- 一、通俗原理:Selenium就是你的“机器人助理”
- 二、环境配置:10分钟跑通Selenium
- 三、元素定位:找到页面上的“机关按钮”
- 四、核心交互操作:让机器人动起来
- 五、等待机制:解决“元素还没加载完”的问题
- 六、完整实战案例:爬取动态加载的新闻列表
- 七、Selenium的常见报错与解决方案
-
- 7.1 `selenium.common.exceptions.WebDriverException: Message: unknown error: cannot find Chrome binary`
- 7.2 `selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element`
- 7.3 浏览器闪退或自动关闭
- 7.4 `selenium.common.exceptions.TimeoutException`
- 7.5 `selenium.common.exceptions.ElementClickInterceptedException`
- 7.6 `SessionNotCreatedException: Unable to find a matching set of capabilities`
- 7.7 网站检测到Selenium并封禁
- 八、无头模式:让浏览器在后台运行
- 九、Selenium的优缺点总结
- 十、与requests的对比总结
- 十一、总结
- 十二、课后作业
- 🔗《20节课精通网页爬虫》系列课程导航
学习目标
学完这一课,你将能够:
- 理解Selenium原理——知道它是一个能“遥控”真实浏览器的自动化工具,而不是又一个“模拟请求”的库
- 完成环境配置——顺利安装Selenium、配置浏览器驱动(用WebDriver Manager告别版本不匹配的痛苦)
- 编写第一个自动化脚本——用代码打开Chrome浏览器、访问指定网页、获取动态渲染后的HTML
- 掌握元素定位——用
find_element()结合各种定位器(ID、XPath、CSS选择器)找到页面上的按钮、输入框 - 模拟用户操作——实现点击、输入文字、翻页等核心交互动作
- 处理加载等待——学会用隐式等待和显式等待解决“元素还没出现就操作”的问题
- 收集动态数据——从渲染后的页面中提取BeautifulSoup无法直接获取的异步加载内容
- 解决常见报错——遇到驱动版本不匹配、元素找不到、浏览器闪退等问题时能独立排查
这一课我们把Selenium带到你的工具箱里。上节课我们讲明白了“为什么requests拿不到动态数据”,这节课我们就要用真正的浏览器去攻克那些“只有真实浏览器才能渲染”的网页。
一、通俗原理:Selenium就是你的“机器人助理”
1.1 回忆上节课的痛点
上节课我们发现:很多网页的“查看源代码”里是空的,真正的数据是浏览器执行JavaScript后才动态渲染出来的。用requests.get()拿到的HTML只是一个架子,BeautifulSoup在里面根本找不到商品列表。
问题的本质:requests是一个“文字通讯兵”——它只负责收发文本。而现代网页请求的往往是“要执行代码”的页面,服务器返回的HTML里包含JavaScript程序,浏览器需要把这段程序运行起来,才能见到最终内容。
1.2 Selenium是更聪明的方案
如果说requests是一个“快递员”——你给他地址,他带回包裹(HTML)就完成任务了。那么Selenium就是一个“真人克隆”——它打开一个真实的浏览器(Chrome、Firefox等),在里面完成所有人类能做的事:输入网址、等待加载、点击按钮、滚动页面、填写表单……然后把你需要的数据取回来。
你可以这样理解:
requests:派一个信使去服务器拿文件,但信使看不懂文件里的“代码指令”- Selenium:派一个机器人坐在电脑前,用真实浏览器打开网页,让浏览器自己执行所有代码,然后机器人把屏幕上出现的内容拍下来给你
1.3 Selenium能做什么?
| 能力 | 说明 |
|---|---|
| 打开浏览器 | 真实启动Chrome/Firefox/Edge窗口 |
| 访问网页 | 自动输入URL并加载页面,等待全部JS执行完 |
| 查找元素 | 通过ID、XPath、CSS选择器等方式定位页面元素 |
| 模拟点击 | 自动点击按钮、链接 |
| 输入文字 | 在输入框里自动填写文本 |
| 滚动页面 | 模拟鼠标滚动,触发懒加载内容 |
| 截图 | 把当前浏览器窗口截成图片保存 |
| 获取渲染后的HTML | 拿到包含动态数据的完整页面源码 |
| 执行JS脚本 | 直接在浏览器里运行自定义的JavaScript代码 |
1.4 什么时候用Selenium?
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 数据在HTML源码中(静态) | requests + BeautifulSoup |
速度快,资源占用少 |
| 数据通过XHR接口返回 | 直接请求接口(上节课的“接口逆向”) | 最快、最高效 |
| 接口有复杂加密/验证码 | Selenium | 免去逆向JS的麻烦 |
| 需要模拟用户行为(登录、点赞) | Selenium | 天然支持交互 |
| 页面滚动加载(无限滚动) | Selenium | 可模拟滚动并等待新内容 |
一句话选型原则:能直接用requests就别上Selenium;但当你发现用requests根本拿不到数据时,就是Selenium出场的时候。Selenium是你的“备用大招”,不是第一选择。
二、环境配置:10分钟跑通Selenium
2.1 安装Selenium库
打开命令行,输入:
pip install selenium
验证安装:
python -c "import selenium; print(selenium.__version__)"
如果输出版本号(如4.15.2),说明安装成功。Selenium 4.x 要求Python 3.7及以上版本。
2.2 浏览器驱动的核心问题
Selenium需要一个“中间人”来指挥浏览器——这个中间人叫WebDriver。以Chrome为例,这个中间人叫chromedriver.exe。
在Selenium 4之前,你需要:
- 查看Chrome浏览器的版本号(设置→关于Chrome)
- 去
chromedriver.chromium.org下载完全匹配版本的驱动 - 把
chromedriver.exe放到项目文件夹或系统PATH里 - 每次Chrome自动更新后,驱动就可能失效,又要重新下载匹配
这个过程非常繁琐,也是Selenium初学者最大的拦路虎。
2.3 Selenium 4的改进:Selenium Manager
从Selenium 4.6版本开始,引入了一个叫Selenium Manager的工具。当你创建webdriver.Chrome()实例时,它会自动:
- 检测你电脑上Chrome的版本
- 自动下载对应版本的
chromedriver - 自动配置好路径
你基本上不用再手动处理驱动问题了!
2.4 备选方案:webdriver-manager(更稳妥)
虽然Selenium Manager已经相当好用,但有时候会因为网络问题下载失败。我们再用webdriver-manager做个双保险:
pip install webdriver-manager
2.5 最简化启动代码
# 方式一:Selenium 4的Selenium Manager自动处理驱动(推荐新手)
from selenium import webdriver
driver = webdriver.Chrome() # 自动下载并启动Chrome
driver.get("https://www.baidu.com")
print(driver.title) # 打印页面标题
driver.quit() # 关闭浏览器
如果你遇到WebDriverException或网络下载失败,用方式二兜底:
# 方式二:用webdriver-manager(更稳定的备选方案)
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
driver.get("https://www.baidu.com")
print(driver.title)
driver.quit()
两种方式任选一种即可。如果网络环境较差(比如公司内网或下载chromedriver一直卡住),优先选用第二种,它会把驱动缓存到本地,一次性下载成功后后续直接复用。
2.6 配置浏览器选项(可选)
在启动浏览器前,可以通过Options对象做一些配置:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--start-maximized") # 启动时最大化窗口
options.add_argument("--disable-blink-features=AutomationControlled") # 降低被检测风险
# options.add_argument("--headless") # 无头模式(不显示窗口,适合服务器环境)
driver = webdriver.Chrome(options=options)
# 或结合 webdriver-manager: driver = webdriver.Chrome(service=service, options=options)
2.7 验证安装:完整的Hello World脚本
from selenium import webdriver
import time
# 创建驱动实例
driver = webdriver.Chrome()
# 访问百度
driver.get("https://www.baidu.com")
# 等待2秒,让你看到浏览器窗口弹出来了
time.sleep(2)
# 获取页面标题
title = driver.title
print(f"页面标题: {title}") # 应该输出“百度一下,你就知道”
# 获取当前URL
current_url = driver.current_url
print(f"当前URL: {current_url}")
# 关闭浏览器
driver.quit()
print("✅ Selenium环境配置成功!")
把这个脚本保存为test_selenium.py,运行:
python test_selenium.py
如果浏览器窗口成功弹出、自动访问百度、最后关闭,说明你的Selenium环境已经配置好了。
⚠️ 注意:如果你的电脑上安装的是Edge浏览器而非Chrome,把
webdriver.Chrome()换成webdriver.Edge()即可。Selenium Manager同样会自动下载Edge WebDriver。
三、元素定位:找到页面上的“机关按钮”
Selenium要模拟点击或输入,首先要在网页中找到那个元素(按钮、输入框、链接)。就像你要打电话,得先找到电话号码簿上的那一条记录一样。
3.1 八大定位方式速览
Selenium通过find_element()方法查找单个元素,通过find_elements()查找多个。定位的具体“坐标”由By类型指定:
from selenium.webdriver.common.by import By
# 单个元素
element = driver.find_element(By.ID, "kw") # 通过ID属性
element = driver.find_element(By.NAME, "wd") # 通过name属性
element = driver.find_element(By.CLASS_NAME, "s_ipt")# 通过class属性
element = driver.find_element(By.TAG_NAME, "input") # 通过标签名
element = driver.find_element(By.LINK_TEXT, "新闻") # 通过超链接的完整文字
element = driver.find_element(By.PARTIAL_LINK_TEXT, "新") # 超链接的部分文字
element = driver.find_element(By.XPATH, "//input[@id='kw']") # XPath表达式
element = driver.find_element(By.CSS_SELECTOR, "#kw") # CSS选择器
# 多个元素(返回列表)
elements = driver.find_elements(By.CLASS_NAME, "item")
3.2 最常用的几种定位方式详解
| 定位方式 | 语法 | 适用场景 | 优先级 |
|---|---|---|---|
| ID | By.ID, "element_id" |
元素有唯一id属性 | 🌟🌟🌟 最高 |
| CLASS_NAME | By.CLASS_NAME, "class_name" |
按CSS类名找 | 🌟🌟 较高 |
| CSS选择器 | By.CSS_SELECTOR, "#id .class" |
灵活强大,熟悉CSS语法 | 🌟🌟🌟 最高 |
| XPath | By.XPATH, "//div[@class='item']" |
全能方案,但稍慢 | 🌟🌟 较高 |
建议:优先用ID;ID没有就仔细构造CSS选择器;实在复杂再用XPath。
3.3 实战演示:在百度搜索框中输入文字
以百度首页为例,搜索框的HTML结构:
<input type="text" class="s_ipt" name="wd" id="kw" autocomplete="off">
我们有多个定位方式可以找到它:
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_input = driver.find_element(By.ID, "kw")
# 方法2:通过NAME定位
# search_input = driver.find_element(By.NAME, "wd")
# 方法3:通过CSS选择器
# search_input = driver.find_element(By.CSS_SELECTOR, "#kw")
# 方法4:通过XPath
# search_input = driver.find_element(By.XPATH, "//input[@id='kw']")
# 在输入框中输入文字
search_input.send_keys("Selenium教程")
# 找到“百度一下”按钮并点击
search_button = driver.find_element(By.ID, "su")
search_button.click()
# 等待结果加载
time.sleep(3)
print(f"搜索完成!当前URL: {driver.current_url}")
driver.quit()
当你想在页面里填入账号密码、模拟点击登录按钮时,用的就是这两个核心动作:send_keys()填文本,click()点按钮。
四、核心交互操作:让机器人动起来
4.1 输入文字:send_keys()
# 在输入框中输入文本
element = driver.find_element(By.ID, "username")
element.send_keys("my_username")
# 清除输入框原有内容(比如清空占位符文字)
element.clear()
element.send_keys("new_password")
4.2 点击:click()
# 点击按钮 & 链接
login_btn = driver.find_element(By.ID, "login-btn")
login_btn.click()
4.3 获取元素中的文本和属性
# 获取元素的文本内容(比如 标题、价格)
title_text = driver.find_element(By.CLASS_NAME, "product-title").text
print(title_text)
# 获取元素的属性值
img_url = driver.find_element(By.TAG_NAME, "img").get_attribute("src")
href_url = driver.find_element(By.TAG_NAME, "a").get_attribute("href")
4.4 滚动页面:模拟下拉
# 滚动到底部
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# 滚动到某个元素的位置
element = driver.find_element(By.ID, "footer")
driver.execute_script("arguments[0].scrollIntoView();", element)
# 滚动指定像素(向下500像素)
driver.execute_script("window.scrollBy(0, 500);")
4.5 翻页与点击翻页按钮
# 常见的翻页按钮定位方式
next_btn = driver.find_element(By.LINK_TEXT, "下一页")
next_btn.click()
# 或者定位具体的页码
page_2 = driver.find_element(By.XPATH, "//a[text()='2']")
page_2.click()
4.6 获取渲染后的页面源码(最关键!)
拿到完整的、包含动态数据的HTML,就可以用BeautifulSoup继续解析了——这也意味着你的Selenium代码可以和之前的静态爬虫解析逻辑完全对接。
# 获取当前页面的完整HTML(所有JS执行完之后)
html = driver.page_source
# 然后可以配合BeautifulSoup继续解析
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
items = soup.find_all('div', class_='product-item')
这是Selenium最核心的价值:driver.page_source拿到的HTML,就是你在Chrome里“右键→检查”看到的结构。所有动态加载的数据都已经在里面了。
五、等待机制:解决“元素还没加载完”的问题
这是Selenium爬虫最常遇到的坑——你让机器人去点击一个按钮,但这个按钮要等2秒后才出现在网页上,机器人那一瞬间找不到它,就报错崩溃了。
5.1 强制等待(不推荐)
import time
time.sleep(3) # 无论元素是否有已经加载好,都等死3秒
缺点:效率极低。如果元素0.5秒就加载好了,你还是要等3秒;如果3秒不够,照样报错。但在调试阶段临时使用,可以帮你快速确认是不是“没等够”导致的问题。
5.2 隐式等待(全局设置)
原理:设置一个最大等待时间,Selenium在查找元素时,如果没找到,会继续等待一小段时间反复尝试,直到超时才报错。隐式等待的设置对页面上所有的find_element操作都生效。
driver = webdriver.Chrome()
driver.implicitly_wait(10) # 最多等待10秒
# 后面的find_element如果找不到元素,会自动等待最多10秒
# 元素一旦出现,就会立即继续执行
element = driver.find_element(By.ID, "some-slow-element")
适用场景:页面整体加载较慢,但没有特别复杂的异步条件。
5.3 显式等待(最精确、最推荐)
原理:针对某一个具体的元素,设置一个最长等待时间,并指定一个“条件”(比如“元素可见”“元素可点击”),条件满足就立即往下执行,超时才报错。
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 等待按钮变得可点击(最多10秒)
wait = WebDriverWait(driver, 10)
button = wait.until(EC.element_to_be_clickable((By.ID, "submit-btn")))
button.click()
5.4 常用预期条件(expected_conditions)
| 条件 | 说明 |
|---|---|
EC.presence_of_element_located((By, locator)) |
元素存在于DOM树中(不一定可见) |
EC.visibility_of_element_located((By, locator)) |
元素可见(宽高>0) |
EC.element_to_be_clickable((By, locator)) |
元素可见且可点击(用于按钮) |
EC.text_to_be_present_in_element((By, locator), text) |
元素的文本中包含某些词 |
5.5 三大等待方式对比
| 类型 | 用法 | 优点 | 缺点 |
|---|---|---|---|
| 强制等待 | time.sleep(3) |
简单,适合快速调试 | 浪费大量时间,效率最低 |
| 隐式等待 | driver.implicitly_wait(10) |
一处设置,全局生效 | 不够精确,无法针对复杂条件 |
| 显式等待 | WebDriverWait(...).until(...) |
最精确,针对特定条件 | 代码稍长 |
实战建议:通常隐式等待 + 显式等待结合使用。隐式设置一个较短的时间,显式针对关键元素再加一层等待。
六、完整实战案例:爬取动态加载的新闻列表
6.1 目标分析
假设我们要爬取一个“滚动到页面底部自动加载更多”的新闻网站。这种网站用requests+BeautifulSoup只能拿到第一屏的HTML,滚动后新出现的内容完全拿不到。
6.2 完整代码(可直接运行)
以下代码以http://quotes.toscrape.com/js/为例(这是一个专为爬虫练习设计的JS动态加载页面):
"""
Selenium实战:爬取动态加载的名言列表
目标页面:http://quotes.toscrape.com/js/ (所有名言通过JS动态渲染)
提取字段:名言内容、作者、标签
展开:模拟滚动到底部,触发懒加载无限滚动
"""
import time
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
# 1. 启动浏览器(如果需要无头模式可去掉--headless的注释)
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--start-maximized")
# options.add_argument("--headless") # 无头模式,不显示窗口
driver = webdriver.Chrome(options=options)
driver.implicitly_wait(5) # 全局隐式等待
# 2. 访问目标页面
url = "http://quotes.toscrape.com/js/"
driver.get(url)
print(f"访问页面: {url}")
# 3. 等待名言元素出现(显式等待)
wait = WebDriverWait(driver, 10)
wait.until(EC.presence_of_element_located((By.CLASS_NAME, "quote")))
# 4. 模拟滚动加载更多(演示滚动功能,本例实际不需要滚动就能显示全部名言)
# 滚动到底部的代码
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(1) # 等待可能的新内容加载
# 5. 提取数据
quotes_divs = driver.find_elements(By.CLASS_NAME, "quote")
print(f"找到 {len(quotes_divs)} 条名言数据")
print("-" * 60)
for i, quote_div in enumerate(quotes_divs, 1):
# 在元素块内继续使用 find_element(注意要用相对选择器 . 避免全文档错误定位)
text = quote_div.find_element(By.CLASS_NAME, "text").text
author = quote_div.find_element(By.CLASS_NAME, "author").text
# 获取标签(可能有多个,用 find_elements)
tags = [tag.text for tag in quote_div.find_elements(By.CLASS_NAME, "tag")]
print(f"{i:2}. 名言: {text}")
print(f" 作者: {author}")
print(f" 标签: {', '.join(tags)}")
print("-" * 60)
# 4. 可选:获取渲染后的完整HTML(备用)
html_source = driver.page_source
with open("quotes_dynamic.html", "w", encoding="utf-8") as f:
f.write(html_source)
print("\n✅ 完整HTML已保存到 quotes_dynamic.html")
# 5. 关闭浏览器
driver.quit()
print("✅ 任务完成,浏览器已关闭")
运行这段代码,浏览器会自动打开、访问名言网站,然后打印出所有动态渲染的名言内容。这是你第一次用Selenium拿到requests拿不到的数据。
七、Selenium的常见报错与解决方案
7.1 selenium.common.exceptions.WebDriverException: Message: unknown error: cannot find Chrome binary
原因:Selenium找不到Chrome浏览器的可执行文件(通常是系统PATH中没有Chrome)。
解决:
- Windows:确认Chrome安装在默认路径(如
C:\Program Files\Google\Chrome\Application\chrome.exe) - 或手动指定Chrome路径:
options = Options() options.binary_location = r"C:\Program Files\Google\Chrome\Application\chrome.exe" driver = webdriver.Chrome(options=options)
7.2 selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element
原因:元素定位器写错了,或元素还没有加载完成(最频繁的Selenium异常)。
解决:
- 用F12检查元素定位器是否正确。
- 增加等待(隐式等待或显式等待)。
- 检查元素是否在
iframe中——你需要先把driver切换到iframe内部:driver.switch_to.frame("iframe_id") - 使用
find_elements(返回列表)而不是find_element(抛异常)来验证定位器是否有效。
7.3 浏览器闪退或自动关闭
原因:driver.quit()被意外调用;或浏览器驱动与浏览器版本严重不匹配,导致连接断开。
解决:
- 检查代码中没有过早调用
driver.quit()。 - 更新Chrome和chromedriver到最新版。
- 如果使用
webdriver-manager,重新运行让它重新下载匹配的驱动。
7.4 selenium.common.exceptions.TimeoutException
原因:显式等待时间内,条件始终未满足(网页太慢或元素根本不会出现)。
解决:
- 增加等待时间。
- 检查你等待的条件是否正确(比如应该是
visibility_of_element_located而不是presence_of_element_located)。 - 用
time.sleep()临时调试,确认究竟需要等多久。
7.5 selenium.common.exceptions.ElementClickInterceptedException
原因:要点击的元素被其他元素挡住(比如悬浮广告、弹窗)。
解决:
- 先关闭挡住的元素(如果有关闭按钮)。
- 无解则用JS强制点击:
driver.execute_script("arguments[0].click();", element)
7.6 SessionNotCreatedException: Unable to find a matching set of capabilities
原因:chromedriver版本与Chrome浏览器版本严重不匹配。
解决:这是驱动管理的经典难题。最稳妥的方式:使用webdriver-manager让它自动匹配一个兼容的驱动版本:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
7.7 网站检测到Selenium并封禁
原理:有些网站会检测WebDriver标志、用户代理字符串、窗口大小等特征来识别自动化工具。
解决方案(基础版):
options = Options()
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_argument("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36") # 再带上浏览器真实UA
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=options)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
})
后续在进阶课程中会专门深入反检测。本课你先跑通基础功能,并在爬虫练习网站(quotes.toscrape.com)上验证——它100%不会封你。
八、无头模式:让浏览器在后台运行
有时候,你不想看到一个窗口弹来弹去(尤其是在服务器上运行爬虫)。这时可以启用无头模式(Headless Mode)——浏览器在后台运行,不显示界面。
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--headless") # 此行启用无头模式
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
driver = webdriver.Chrome(options=options)
driver.get("https://www.baidu.com")
print(driver.title) # 控制台正常输出,但没有窗口弹出
driver.quit()
注意:无头模式下的浏览器行为和带窗口的略有差异(比如截图尺寸默认不同),且更容易被某些网站检测到反爬。
九、Selenium的优缺点总结
9.1 优点
| 优点 | 说明 |
|---|---|
| 所见即所得 | 能拿到JS动态加载的全部内容,网页长什么样就爬什么 |
| 免逆向JS | 不用分析参数加密,绕过了很多动态反爬 |
| 模拟真实用户 | 支持点击、滚动、键盘输入,最大程度模拟人类行为 |
| 调试方便 | 看到浏览器窗口就知道哪一步出错了 |
9.2 缺点
| 缺点 | 说明 |
|---|---|
| 速度慢 | 每次都要启动浏览器、加载CSS/JS、渲染,比requests慢几十倍 |
| 资源占用高 | 一个浏览器实例常占200~500MB内存 |
| 容易被检测 | 有经验的网站可以识别WebDriver标志 |
| 不稳定 | 依赖浏览器版本,经常需要维护驱动更新 |
十、与requests的对比总结
| 对比维度 | requests + BeautifulSoup |
Selenium |
|---|---|---|
| 速度 | 极快 | 较慢 |
| 上手难度 | 低 | 中等 |
| 能否执行JS | ❌ 不能 | ✅ 能 |
| 能否获取动态渲染后HTML | ❌ 不能 | ✅ 能 |
| 资源占用 | 低 | 高 |
| 反爬对抗能力 | 需手动破解 | 天然模拟真实浏览器 |
| 适用场景 | 静态页面、API逆向 | 动态页面、交互式操作 |
最佳实践:
- 先尝试用
requests找XHR接口(最快、最佳) - 接口搞不定或页面完全不可逆时,再上Selenium
Selenium是你的攻城锤,而非手术刀——特定场合的作用无可替代,但不必每次都用。
十一、总结
本课核心知识清单
| 知识点 | 掌握程度 |
|---|---|
| Selenium原理 | 知道什么是WebDriver、Selenium Manager |
| 环境搭建 | 能独立安装并写出第一个启动程序 |
| 元素定位8种方式 | 能灵活切换ID/CSS/XPath |
| 交互操作 | 熟练用send_keys、click、text、get_attribute等 |
| 等待机制 | 能区分强制/隐式/显式等待并恰当使用 |
| 获取动态HTML | 掌握page_source获取完整源码 |
| 常见报错 | 能独立解决NoSuchElementException和驱动不匹配 |
| 无头模式 | 知道如何让浏览器在后台运行 |
承上启下的位置
- 承上:解决了第12课中requests无法处理的动态渲染问题
- 启下:为第14课处理登录验证码、滚动加载等复杂反爬场景打基础
十二、课后作业
作业1:环境搭建与基础运行(必做)
在自己的电脑上安装Selenium,配置浏览器驱动,运行第2.7节的HelloWorld脚本,确保能正常打开百度并打印标题。如果遇到问题,尝试用两种不同的驱动管理方案(Selenium Manager和webdriver-manager)分别测试并记录过程。
作业2:模拟搜索操作(必做)
写一个Selenium脚本,完成以下操作:
- 打开百度
https://www.baidu.com - 在搜索框中输入“Selenium 爬虫”
- 点击“百度一下”按钮
- 等待搜索结果加载完成
- 从结果页提取前5条搜索结果的标题和链接
- 关闭浏览器
要求:必须使用显式等待(WebDriverWait)等待搜索结果出现。
作业3:滚动加载爬取(必做)
访问 http://quotes.toscrape.com/scroll,这个页面采用了无限滚动加载:
- 前三页的名言是直接显示的,第4页需要触发滚动到底部后才显示
- 编写Selenium脚本自动滚动到底部3次,触发新内容加载
- 提取每次滚动后新出现的名言内容
- 最终收集不少于20条名言并输出
提示:可以用driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")触发滚动。
作业4:隐式等待 vs 显式等待对比(选做)
构造一个演示页面(或用http://quotes.toscrape.com/js/),分别用三种等待方式实现:
time.sleep()固定等待driver.implicitly_wait()隐式等待WebDriverWait(...).until(...)显式等待
在代码中打印时间戳记录每一种等待的耗时,对比效率差异,写出你的结论。
作业5:截图保存(必做)
修改作业3的代码,在滚动到底部并完成数据收集后:
- 使用
driver.save_screenshot("result.png")保存当前页面截图 - 将提取的名言数据保存到CSV文件
作业6:常见报错复现与解决(选做)
- 场景A:故意临时修改Chrome浏览器版本(或断开外网),观察驱动下载失败或版本匹配不了的报错,然后用
webdriver-manager加显式处理避免这种错误。 - 场景B:故意写错定位器导致
NoSuchElementException,然后通过增加等待或改用正确的定位器修正。 - 写出每种报错的复现步骤和最终解决方案。
结束语:Selenium的学习曲线比requests稍陡,但一旦掌握,你就拥有了处理任何动态网页的能力。下节课,我们将继续深挖Selenium的高级技巧——等待更多复杂条件、处理多窗口、操作iframe、绕过更高级的反爬检测。
第14课见。
🔗《20节课精通网页爬虫》系列课程导航
🌟 感谢您耐心阅读到这里!
💡 如果本文对您有所启发欢迎:
👍 点赞📌 收藏 📤 分享给更多需要的伙伴。
🗣️ 期待在评论区看到您的想法, 共同进步。
🔔 关注我,持续获取更多干货内容~
🤗 我们下篇文章见~
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)