news 2026/9/9 5:26:09

Selenium安装配置全攻略:浏览器驱动匹配与自动化脚本实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Selenium安装配置全攻略:浏览器驱动匹配与自动化脚本实战

Selenium装不上、跑不通、报一堆错,这个问题我从入行到现在见了至少几百次。上周同事还抱着电脑过来,说昨天能跑的脚本今天早上突然就挂了,启动浏览器那一步直接抛SessionNotCreatedException。我打开chrome://version看了一眼,又看了眼他下载的driver版本,结果一目了然:Chrome自动更新到了新版本,driver还是老版本。

这类问题的根源基本都在环境和依赖配置上,跟代码逻辑关系不大。我今天不打算讲一堆理论,就把自己安装Selenium、配置浏览器驱动、跑通第一个自动化脚本的完整过程,连同踩过的坑和排查套路一起整理出来。如果你是跟着selenium教程学的新手、做web自动化测试的测试开发,或者正打算用selenium爬虫处理动态页面,这篇实操记录可以直接帮你少走两三天弯路。

1. Selenium到底是什么,我为什么还在用它

1.1 几分钟搞清楚Selenium的定位

Selenium是一个Web自动化框架,核心能力就是模拟人在真实浏览器里的点击、输入、滚动、翻页、截图这些操作。它本身不是爬虫框架,但在动态网页、JS渲染页面这种场景下,用requests直接拿不到渲染后的内容,而Selenium能把页面完整地加载出来,然后拿到最终状态下的DOM和数据。

简单做个比喻:Selenium就像一个人坐在电脑前操作浏览器,它通过浏览器驱动(WebDriver)把代码里的指令翻译成浏览器能听懂的话。代码里写click,driver就帮你点一下;代码里写send_keys,driver就帮你敲键盘。整个过程中浏览器是真实运行的,所以你在代码里做的事和手动操作页面几乎没有差别。

1.2 Selenium能干的几件事

第一类:自动化测试,这是它最原始的使用场景,尤其是回归测试。页面改动之后手动跑一遍全流程很痛苦,但用Selenium把用例写成脚本,以后随时一键重跑,效率和稳定性都能显著提升。

第二类:网页数据抓取。很多网站数据是通过异步请求在页面加载后才渲染出来的,直接分析接口又可能遇到加密参数。用Selenium打开浏览器直接取渲染后的页面数据,就能绕开那些加密和构造参数的麻烦。

第三类:重复性操作自动化。比如每天定时登后台下载报表、定时刷新某个商品价格、批量提交表单,凡是手动操作固定的网页流程,写个脚本挂起来,能省下不少时间。

第四类:可视化演示和页面截图。需要在无头浏览器里打开页面截图做数据看板、或者对不同页面状态做对比图,Selenium也都能胜任。

1.3 为什么到今天还在选Selenium

市面上做Web自动化的工具不少,像Puppeteer、Playwright也都是很好的选择。但Selenium有一个其他工具比不了的优势:支持语言广,支持浏览器种类全面,社区用户多。Python、Java、C#、JavaScript都能驱动它,而且Chrome、Firefox、Edge都有对应的官方driver。跨平台能力和开放性决定了它依然是很多企业和测试团队的基础设施。

Selenium 4之后的架构比老版本干净了不少。它正式基于W3C WebDriver标准协议,不再依赖以前那种JSON Wire Protocol,定位元素的新写法也会简洁一些,后面我会演示。

2. 安装Selenium库,从这里开始

2.1 先确认你的基础环境

安装Selenium之前,先确认机器上有Python环境。我个人建议用Python 3.8以上的版本,虽然Selenium 4还支持3.7,但太老的Python版本后续依赖处理会越来越麻烦。

另外一个要点是虚拟环境。这是我的习惯,给每个项目单独建一个独立的Python运行空间,避免不同项目依赖的库版本互相打架。

创建虚拟环境的命令很简单:

python -m venv venv

创建完成后激活环境,Windows和macOS/Linux的命令略有区别:

# Windows venv\Scripts\activate # macOS / Linux source venv/bin/activate

激活后命令行前面会出现(venv)标记,看到这个就说明已经在虚拟环境里了。后面的安装和运行脚本都在这个环境里进行。

2.2 Selenium库的安装命令与国内源加速

Selenium库本身的安装非常直接,用pip就能搞定:

pip install selenium

如果有的时候下载速度慢,或者容易超时,可以换用国内镜像源。以清华PyPI镜像为例:

pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple

实测用镜像源在高峰期下载速度快很多,遇到网络环境不稳定的情况建议直接加这个参数。

装完以后验证一下版本:

python -c "import selenium; print(selenium.__version__)"

如果没报错,并且输出一个类似4.21.0的版本号,那说明库已经装好了。此时离真正跑通只差最关键的一步——浏览器驱动。

2.3 顺便聊聊Java等其他语言引入Selenium的方式

有读者搜过“java引入selenium自动化”,其实思路跟Python完全一致,差别只在于依赖管理方式不同。Java项目用Maven就在pom.xml里加依赖:

<dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>4.21.0</version> </dependency>

引入后照样要配置浏览器驱动。驱动选择规则和Python场景一模一样,所以这篇文章的驱动部分对Java、C#等语言同样适用。

3. 浏览器驱动:整个安装过程中最坑的一环

3.1 为什么要给特定浏览器配特定驱动

很多人第一次装Selenium,装完库就急着写代码,结果一运行就报:

WebDriverException: Message: unknown error: cannot find Chrome binary

或者:

SessionNotCreatedException: Message: session not created

然后人就懵了。问题几乎都出在“没有安装浏览器驱动”或者“驱动版本和浏览器版本不匹配”上。

浏览器驱动的作用,是让Selenium库能和对应浏览器通信。它相当于一个翻译器:代码通过Selenium库发出命令,driver把命令转给浏览器执行;浏览器执行完,再把结果原路返回给代码。不同浏览器有不同driver,Chrome对应chromedriver,Firefox对应geckodriver,Edge对应msedgedriver。

这个“翻译器”和浏览器版本必须匹配,否者沟通就容易出问题,表现出来就是上面那几类异常。

3.2 怎么判断该下载哪个版本的驱动

以Chrome为例,这是绝大多数人的选择,先打开地址栏输入chrome://version并回车。大概率能看到类似这样的信息:

Google Chrome: 122.0.6261.129(正式版本)

真正决定driver版本的是“大版本号”,也就是前面的三位数,这里就是122。我们要下载的chromedriver就是122.0.6261.xx系列,版本号大于等于122或者小于122但不是相近的版本,都可能出问题。核心匹配原则就是:chromedriver大版本号必须和Chrome大版本号一致。比如你的Chrome是118,那就要找118开头的chromedriver。

在chromedriver下载页面能看到大量版本目录。下载时先选跟自己Chrome大版本号一致的目录,再选安装包。Windows选chromedriver-win64.zip,macOS选chromedriver-mac-arm64.zip(Apple芯片)或chromedriver-mac-x64.zip(Intel芯片),Linux选chromedriver-linux64.zip

还有个实用技巧:用webdriver-manager库可以自动匹配并下载合适的driver到本地,省去手动找版本的时间。安装及基本用法如下:

pip install webdriver-manager
from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service service = Service(ChromeDriverManager().install()) driver = webdriver.Chrome(service=service)

这个库会读取你本机Chrome版本,然后自动下载匹配的driver,实测能解决90%以上的版本不匹配问题。如果项目要求可控性高、或者部署环境的网络不允许去外网下载,还是建议手动下载并固定版本。

3.3 驱动下载后怎么放置最省事

手动下载驱动后,最常见也最省事的做法是把它解压后直接放到Python脚本同目录,或者放到一个固定目录。然后在代码里用Service指定driver路径:

from selenium import webdriver from selenium.webdriver.chrome.service import Service service = Service(r"D:\tools\chromedriver\chromedriver.exe") driver = webdriver.Chrome(service=service)

注意r前缀表示原始字符串,路径里的反斜杠不用转义。Windows下尤其需要留意路径写法。

也可以把driver所在的目录加入系统的PATH环境变量。加入后代码里就不用再写Service了,直接:

driver = webdriver.Chrome()

新版Selenium会自动去PATH里找chromedriver。但我个人建议:初学阶段老老实实把驱动放在脚本同目录,用Service显式指定一次,这样出现问题的时候排查路径最直观。

3.4 没有Chrome浏览器的环境怎么办

有些机器上确实没装Chrome,或者不方便安装Chrome。这时可以考虑用微软Edge,Edge浏览器内核也是Chromium。驱动需要配套使用Microsoft Edge WebDriver,它在微软官网有提供。下载时同样需要看Edge浏览器的版本号,在地址栏输入edge://version查看,匹配原则和chromedriver一致。

Firefox则是用geckodriver,这个相对小众一些,一般只有业务要求Firefox兼容测试时才需要用到。

4. 手把手写第一个能跑的自动化脚本

4.1 五步搞定启动浏览器并打开网页

我先给新手一个能直接跑起来的最小示例,不分心,跑通再说别的:

from selenium import webdriver from selenium.webdriver.chrome.service import Service service = Service(r"D:\tools\chromedriver\chromedriver.exe") driver = webdriver.Chrome(service=service) driver.get("https://www.example.com") print(driver.title) driver.save_screenshot("homepage.png") driver.quit()

代码逻辑很直观:

  1. 创建Service对象,指向chromedriver。
  2. 打开Chrome浏览器。
  3. 访问指定网址。
  4. 打印页面标题并截图。
  5. 关闭浏览器。

跑通后屏幕上会闪出一个Chrome窗口并自动打开网站,脚本同目录下会多出一张homepage.png截图。这一步成功,就说明Selenium环境完全ok了,“安装与运行”环节正式过关。

4.2 定位页面元素的常用姿势

跑通环境之后,自动化操作的核心就是定位页面元素。Selenium 4的推荐写法是配合By类,比如:

from selenium.webdriver.common.by import By # 通过ID定位 element = driver.find_element(By.ID, "username") # 通过NAME属性定位 element = driver.find_element(By.NAME, "password") # 通过CSS选择器定位 element = driver.find_element(By.CSS_SELECTOR, "button.login-btn") # 通过XPath定位 element = driver.find_element(By.XPATH, "//input[@placeholder='请输入手机号']")

实际开发中最常用的是ID、CSS_SELECTOR和XPATH三种。ID定位简单稳定,但很多页面的元素没有ID;CSS_SELECTOR简洁高效,前端的DOM结构能看懂就行,缺点是选择器写错时排查有门槛;XPATH表达力最强,可以按文本内容、属性、层级关系定位,但写得太长时冗余且脆弱。

日常的经验是:优先用ID或CSS_SELECTOR,遇到复杂页面才上XPath。

4.3 页面交互:输入、点击、下拉选择

元素定位找到后,就能操作了。输入文本用send_keys,点击用click,清空输入框用clear

driver.find_element(By.ID, "username").send_keys("test_user") driver.find_element(By.NAME, "password").send_keys("123456") driver.find_element(By.CSS_SELECTOR, "button.login-btn").click()

如果要处理下拉框,可以使用Selenium提供的Select类,比如选择省份:

from selenium.webdriver.support.ui import Select select = Select(driver.find_element(By.ID, "province")) select.select_by_visible_text("广东省")

这段代码的意思是:在“省份”下拉框里找到文本为“广东省”的选项并选中它。

4.4 等待机制:为什么Selenium脚本总要在页面加载上栽跟头

新手最容易出现的问题,是driver.get()返回后立刻去找元素,结果报NoSuchElementException。原因是页面URL加载完成,不代表页面里的动态内容渲染完了。尤其现代网站大量使用JavaScript,点击登录按钮后,接口请求、数据回填、元素渲染都需要时间。

等待机制就是解决这个问题的。Selenium里的等待分两种,我会优先推荐显式等待:

from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 等待登录按钮变得可点击,最多等10秒 login_button = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, "button.login-btn")) ) login_button.click()

显式等待的核心思路是:给某个条件设一个最大等待时间,在时间内每隔一小段就去检查一次,条件满足了立刻继续执行,不满足就一直等到超时。例子里的“条件”是按钮可点击,像这样的expected_conditions还有很多,比如visibility_of_element_locatedpresence_of_element_located,应对不同场景。

隐式等待则不同,它是给整个driver设置一个全局的轮询等待时间。比如:

driver.implicitly_wait(10)

之后每次find_element在找不到元素时都会等待一段时间再试。全局好写,但不够灵活。实际页面里某些关键数据可能需要更长的时间渲染,全局等待要么不够要么拖慢整个脚本。所以我的建议是:implicitly_wait可以用来兜底设个较短的全局时间,关键交互节点用显式等待精准控制。如果两者混用,有些版本下会出现等待策略叠加的诡异问题,建议尽量只用一种策略。

5. 常见问题与排查技巧实录

5.1 可以先对照一张报错速查表

遇到报错先别慌,很多Selenium问题类型非常集中。先对照这张速查表:

报错信息常见原因首选处理方案
SessionNotCreatedException: session not createddriver版本与浏览器版本不匹配删除旧driver,下载对应浏览器大版本号一致的driver
WebDriverException: unknown error: cannot find Chrome binary没装Chrome或driver找不到浏览器可执行文件安装Chrome;或页面启动参数指定binary_location
NoSuchElementException元素定位路径不对,或元素还没渲染完成检查选择器;改用显式等待
TimeoutException显式等待超时,条件一直没达成检查条件写法和元素实际状态;适当加大超时时间
ElementNotInteractableException元素被遮挡、隐藏或不可编辑需要等待元素可见;或用JS操作多步点击
InvalidArgumentException参数类型错误,如把路径写错检查传入方法是路径还是对象

表里每一行的“原因”和“方案”都是从实际项目里高度浓缩出来的,基本上照着对号入座就能解决大半问题。

5.2 定位不到元素时的排查套路

NoSuchElementException是最常见的一个异常,我自己的排查顺序是四步走。

第一步,检查选择器是否写对。先在浏览器开发者工具里按Ctrl+Shift+C,在Elements面板中用选择器搜索确认能唯一找到这个元素。如果搜出多个,就要考虑会不会匹配到另一个,改用更精确的选择器。

第二步,检查元素是否在iframe里。如果一个元素的HTML嵌在iframe标签里面,直接在主文档中用find_element是找不到的。需要先切换到iframe:

driver.switch_to.frame("iframe的id或name") # 操作完成后再切回主文档 driver.switch_to.default_content()

这个点非常隐蔽,很多老手也会在这里卡住。

第三步,确认元素是不是在Shadow DOM中。现代前端组件越来越多地把内部结构封装在Shadow DOM里,普通查找方式同样碰不到里面的元素。处理方法是先获取host元素,再用Shadow Root的方式往内部找。为了不把新手绕晕,我只能说如果遇到这种场景,优先让前端开发加测试专用的>from selenium import webdriver from selenium.webdriver.chrome.options import Options options = Options() options.add_argument("--headless=new") options.add_argument("--window-size=1920,1080") driver = webdriver.Chrome(options=options) driver.get("https://www.example.com") driver.save_screenshot("headless.png") driver.quit()

实际跑脚本时无头模式不仅安静,启动速度和资源占用都要好不少。代码里加--window-size=1920,1080是为了设置一个合理的视口大小,保证页面按正常桌面宽度渲染。如果你需要对页面做可视化比对或截图,这个参数尤其重要。

顺便说一下很多爬虫场景做“可视化”,其实就是给每个要监控的页面定时截图存档,再把截图拼成对比图或者录成小动图,用无头浏览器完全扛得住,比每次都开窗口稳定得多。

5.4 driver生命周期管理:quit还是close

部分新手写完driver操作不执行quit(),脚本一结束就完事,结果任务管理器里残留一堆chrome进程,内存越占越高。这样跑一次两次没什么感觉,但做成定时任务、循环跑多个页面时,内存会被慢慢吃光,最后机器越来越卡。

这里要区分两个方法:

  • driver.close():只关闭当前标签页或当前窗口。
  • driver.quit():关闭整个浏览器进程,释放全部driver资源。

正常脚本结束时都应该调用quit()。配合Python的try...finallywith结构,确保即使执行中途报错也能正确关闭异常,不会在环境里留下僵尸进程。

常用写法:

driver = webdriver.Chrome() try: driver.get("https://www.example.com") # 这里写业务逻辑 finally: driver.quit()

如果做的是轻量单次任务,也可以在脚本入口代码执行完毕后直接调用退出。

5.5 我平时习惯遵守的避坑清单

这些年用下来,我总结了一套自己的Selenium踩坑避坑清单,每一条都是从实际报错里长出来的,含金量比文档高不少,分享给各位。

  • 浏览器版本一变,驱动必须跟着变。Chrome更新频率很高,自动更新后脚本很可能立刻挂掉。定时任务最好每次运行前检查一下大版本是否一致,或者写个小函数自动读取浏览器版本再去下载匹配驱动。
  • 元素定位不要死磕单一属性,页面元素尽量通过稳定的业务属性定位,写出的用例才不会因为一次前端改版全部崩掉。
  • 等待时间不要过度贪心。很多人遇到问题就把超时时间调到30秒甚至60秒,这反而会把问题隐藏起来,页面真的卡住了你也要傻等半天,报错反馈来得更慢。一般核心交互等待10秒以内足够。
  • 下载driver时别下错了平台包。Windows的机器务必选win版本,用macOS Apple芯片的机器选mac-arm64,下错了解压后也能跑,但执行时会报错。
  • 目录路径不要带中文或特殊字符,个别环境下会把driver加载卡在奇怪的问题上。

最后补一个细节,脚本里尽量少用time.sleep()固定等待,因为网络快慢波动太大,固定等待要么等不够要么浪费大量时间。用WebDriverWait才是按需等待的真正解法。这种“显式等待优先”的使用习惯,也是我反复跟团队成员强调的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 5:23:52

HJ165 小红的优惠券:贪心与连续区间覆盖的算法解析

第一次看到“HJ165 小红的优惠券”这个标题&#xff0c;很多人的第一反应是“这不就是一道模拟题吗&#xff0c;把优惠券按价格排序然后算一算”。真上手以后才会发现&#xff0c;这道题的精髓根本不是模拟&#xff0c;而是隐藏在“优惠券”这个生活场景后面的连续区间覆盖和贪…

作者头像 李华
网站建设 2026/9/9 5:21:30

Open3D体素质心下采样:无人机点云预处理与可视化实战

点云数据一多起来&#xff0c;最先想到的不是什么高深算法&#xff0c;而是怎么“减负”。我在处理无人机航测点云时&#xff0c;一个架次下来往往几千万个点&#xff0c;直接扔进算法里跑&#xff0c;内存先崩为敬。这种场景下&#xff0c;Open3D 里最常见的降采样手段就是体素…

作者头像 李华
网站建设 2026/9/9 5:21:28

串口通信全双工与半双工:从RS232到交换机25GE口配置

打开串口调试助手&#xff0c;点了“发送”按钮&#xff0c;下面的接收区却半天没反应&#xff1b;或者RX计数跳得飞快&#xff0c;TX计数却纹丝不动。这时候很多人第一反应是“板子坏了”。但我在实际调试中见过太多类似情况&#xff0c;最后查出来根本不是硬件问题&#xff0…

作者头像 李华
网站建设 2026/9/9 5:20:04

大华摄像头Web播放SDK集成实践:从RTSP到浏览器实时预览

简介&#xff1a;浙江大华摄像头Web3.0网页播放SDK插件包面向网页开发者&#xff0c;用于将大华摄像头视频流快速集成到Web应用&#xff0c;实现远程实时预览、历史回放与云台控制&#xff0c;适合安防监控类项目二次开发。资源共6个文件&#xff0c;压缩包仅4.24MB&#xff0c…

作者头像 李华
网站建设 2026/9/9 5:17:23

RH124第二章访问命令行:终端、Shell与命令结构全解析

1. 为什么每个RH124学习者都绕不开命令行这一章RH124&#xff08;Red Hat System Administration I&#xff09;是红帽认证体系里最基础也是最重要的一门课&#xff0c;专门面向刚接触Linux系统管理的初学者。很多人觉得第二章"访问命令行"太简单——无非就是打开终端…

作者头像 李华