先问一个几乎所有刚接触"测试"的同学都会问的问题:我已经会写代码了,为什么还要学自动化测试?尤其是"UI 自动化"这种听起来就很麻烦的事,为什么不用人肉点点点?

答案有一个关键前提:手工点一遍要五分钟,跑一遍要五分钟、十遍还是五分钟,而且人会有状态起伏、会点错、会漏看。自动化脚本则是"我写一遍,跑一万遍都不累、都不错"。当你要回归测试一个系统、要在大版本发布前把几十个功能用例全部过一遍的时候,一双手远远不够用。而 UI 自动化(也叫"界面自动化""端到端测试")要解决的就是这个问题:让一段程序像真实用户一样打开浏览器、在页面里输入、点击、翻页、提交,最后验证结果对不对。

在众多 UI 自动化工具里,Selenium 是最老牌、生态最成熟、几乎成为测试行业"默认选项"的那一个。这篇博客就是它的"零基础安装与入门"。我们从最底层的概念讲起——Selenium 到底是什么、WebDriver 又凭什么能"遥控"浏览器,然后一步步把环境搭起来:装浏览器、装语言、装开发工具、装驱动、装框架,最后写一个真正能跑起来的第一脚本,并把新手入门最容易栽进去的那些启动坑一个个掰开把脉。

说实话,安装 Selenium 这条路,90% 的同学卡住的点根本不在"不会写代码",而在环境的"五脏六腑"没通气:版本不匹配、PATH 没配、驱动下载不下来。所以这篇我会把安装过程中的"坑"当成主角一样写,你照着走,尽量不踩雷。

你需要的知识准备

在往下走之前,建议你先有下面这些很基础的底子,都是常识级的东西,没有也不用慌,我会一边讲一边补:

  • 图形界面浏览器的概念:你日常用的 Chrome、Edge、Firefox。自动化就是操控这些"真浏览器",而不是模拟器。
  • 命令行终端(cmd / PowerShell):你至少要会在 Windows 上打开一个命令行窗口,能往里面敲命令。
  • "环境变量"这个词眼熟:后面讲 PATH、讲配置驱动,会反复出现。我先给你一个粗印象:环境变量就是操作系统给程序看的"全局便签",上面记着"某某东西装在哪、某某程序该从哪里找"。
  • 一点编程常识:哪怕只会一句 print 也够。我们首选的自动化脚本语言是 Python,因为它是 Selenium 教学的最主流选择,三行代码就能开一个浏览器。

如果你上面哪条没接触过,也没关系。这一篇的重点恰恰就在"手把手",我会把每一步都拆到不能再拆。


Selenium 是什么,我们为什么要它

先解决第一个名词。Selenium 是一个用于"浏览器自动化"的工具集,它的英文发音大概读作"瑟勒尼姆"(跟化学元素"硒"同一个词)。我们可以准确一点定义它:Selenium 是一套由官方和社区维护的、支持多种编程语言的库和协议体,让程序能够启动浏览器、控制浏览器执行真实的页面交互,从而自动完成测试或重复性的网页操作。

注意我用了"库+协议体"这个说法,是因为 Selenium 其实是一个"三层"的东西,很多人把它简单理解成"一个库"其实不太完整:

  • 客户端库(Client Library):就是你在代码里 import 的那个东西,比如 Python 的 selenium 库、Java 的 selenium-java。它们充当你的"遥控器手柄"。
  • WebDriver 协议(后面专讲):手柄和浏览器之间的"通信语言"。
  • 浏览器驱动(Driver):真正在每台机器上把"遥控信号"翻译成浏览器动作的那个小程序。

这三层配合起来,才构成我们常说的 Selenium。官方给它的定位是"用于 Web 应用程序的测试工具",但它能干的远不止测试:网页爬数据、自动填表、自动截图、批量导出报表……凡是"人能在浏览器里重复做的操作",理论上都能脚本化。

这里有个大实话必须说清楚:Selenium 是"UI 自动化",它模拟的是真实用户在页面上的操作,走的是真实浏览器;这和"接口自动化"(直接调后端 HTTP 接口测数据)是两条完全不同的路。 Selenium 重、慢、对环境挑剔,但它验的是"用户端到端"的真实体验,这正是接口自动化验证不到的东西。二者互补,测试岗位通常都要会。

自动化脚本与"元素定位"两个词先亮相

正文里马上会用到两个词,先给定义。自动化脚本,指的就是"记录并执行自动化操作步骤的那段代码/程序",它是"你的意图的文字化"——你不是手点,而是把每一次点击、每一次输入都写成代码让机器去执行。

元素定位(Element Location),指的是"程序如何在页面的 HTML 结构里,找到你要操作的那个输入框、那个按钮"。因为页面在你面前是一张图,但程序眼里它是一棵由标签组成的树,你得告诉程序"我要找的那个东西长什么样、藏在哪"。定位靠的是 id、name、CSS 选择器、XPath 这类"地址"。这是 Selenium 入门的第二个坎,这篇的脚本会用到一种最简写法,后面我会解释。

Selenium 支持哪些语言?——关于 C++ 方向的一句实话

很多同学带着"我要用 C++ 写自动化"的执念来问,这里必须给你一个准确的事实,免得你绕弯路:Selenium 官方提供的客户端库支持 Python、Java、C#、Ruby、JavaScript、Kotlin 这些语言,但官方并不提供 C++ 绑定。 这是 Selenium 的既定事实。所以"用 C++ 直接调 Selenium"在官方意义上是不成立的。

那 C++ 方向的同学怎么办?通常有两条务实路径:一是搭一个 Python/Java 的 Selenium 测试工程来驱动浏览器(测试逻辑往往相对独立,不必和产品代码同一语言);二是直接用 WebDriver 的 HTTP 接口(Selenium 4 之后是标准的 W3C WebDriver 协议,本质是一组 HTTP 请求),让 C++ 通过发送这些请求来控制浏览器,等于用 C++ 手写一个"裸客户端"。第二条路很硬核,适合进阶,不在这篇入门范围内。为了不让你绕弯,也为了贴合绝大多数课堂/岗位的实际选型,本教程的每一个命令、每一段脚本都采用 Python 演示,这也是全行业 Selenium 教程默认的第一语言。

小结:Selenium = 客户端库 + WebDriver 协议 + 浏览器驱动,三者齐活才能"遥控"浏览器。语言选型上官方有 Python/Java/C#/Ruby/JS/Kotlin,唯独没有官方 C++ 绑定,C++ 团队通常借 Python/Java 或直连 WebDriver 协议来落地。


WebDriver:程序凭什么能"遥控"浏览器

第二个必须讲清的关键名词是 WebDriver(网页驱动)。它既是一个协议,也是一套接口标准。用大白话说:WebDriver 定义了一整套"程序 ↔ 浏览器"之间怎样对话的规则,让程序可以像遥控器一样指挥浏览器做打开、输入、点击、提价、后退这类动作。

为什么需要这么个中间层?因为浏览器厂商(Google 的 Chrome、微软的 Edge、Mozilla 的 Firefox)都有自己庞大的内部实现,你不可能让每一份额外代码都去猜每个浏览器内部的 API。于是大家坐下来定了一个统一标准:浏览器开放一个"遥控端口",对外提供一套规约好的能力(就叫 WebDriver),任何语言只要按这套规约发指令,就能驱动任何实现了该标准的浏览器。 这跟你家不同牌子的电视都支持 HDMI 接口是一个道理——接口标准统一了,遥控器就能通用。

Selenium 4 以后,遵循的就是 W3C(万维网联盟)制定的标准 WebDriver 协议。这套协议本质上是 HTTP 请求:你的 Python 脚本发出一个形如 POST /session、POST /element/find 之类的请求,浏览器驱动把这些请求翻译成真的浏览器动作。你不需要手写这些请求,Selenium 客户端库替你封装好了。

再强调一遍刚才那三个角色的协作流程,一眼看懂:

你的脚本(Python)
      │  调用 selenium 客户端库
      ▼
Selenium WebDriver(客户端连接)
      │  HTTP 请求,走 WebDriver 协议
      ▼
浏览器驱动(如 chromedriver)
      │  把协议指令翻译成浏览器原生动作
      ▼
Chrome / Edge / Firefox 浏览器

这条链路里,中间那个"浏览器驱动"就是最容易出问题的环节,我们在"版本匹配"那一节专门收拾它。

思考题:为什么不能"直接调浏览器",非要绕一圈 WebDriver?

【思考题 1】 既然 WebDriver 中间隔了两层(客户端 + 驱动),我们为什么不让脚本直接去操控浏览器?这样不是更快更直接吗?

【答案详解】 核心原因是"标准"与"解耦"。第一,直接调浏览器意味着你的脚本要分别适配 Chrome、Edge、Firefox 三套互不相同的内部接口,写一套只适用于一种浏览器,换个浏览器就全废;而 WebDriver 把"浏览器能力"抽象成了统一标准,一套脚本通吃所有支持该标准的浏览器。第二,浏览器通常以独立进程运行在一个拥有自己安全边界的沙箱里,直接往别的进程里"伸手"既不安全也不稳定,浏览器厂商也不会开放这种原生的、可被任意外部程序直接控制的开发接口给你随便调。第三,WebDriver 作为标准协议,天然把"谁来写客户端库"和"谁能接入浏览器"这两件事解耦开——Python、Java、C# 各写各的客户端,但都能操纵同一个浏览器驱动,生态因此繁荣。一句话:绕这一圈,换来的是"一次编写、多方适配、跨语言通用",还把它做成了安全可控的标准通道。


环境准备第一步:装一个正版浏览器

从这一步开始动手。Selenium 自动化是"遥控真实浏览器",所以电脑上至少得有一个能用的图形浏览器。 课堂和本教程统一以 Chrome(谷歌浏览器)演示,Edge、Firefox 原理相同,驱动名字和下载地址略有差异而已。

这里有一条被无数人忽略、却真实发生过很多次的坑,务必当回事:

浏览器必须是从官网下载的正版安装包。

根据以往课堂的经验,确有部分同学的电脑上装的是"混合版""绿色版""魔改版"浏览器——路径怪异、组件被精简、底层接口被动过手脚。这样的浏览器即使能正常上网,WebDriver 去驱动它时也会莫名其妙失败:驱动连不上、页面打不开、或者启动即闪退。所以第一步就从源头排查:去 www.google.com/chrome 下载官方安装包安装。 别图方便去下载站随便拉一个,那个可能带着全家桶或残缺组件,成为日后"别人能跑你不能跑"的头号嫌疑。

装浏览器时有两点顺便记住:

  • 记住它装在哪里,后面有手动配驱动路径的场景会用到。Windows 默认一般装在 C:\Program Files\Google\Chrome\Application\,可执行文件叫 chrome.exe。
  • Chrome 会自动更新。这对你来说是好事,但那句"驱动要匹配版本"的坑就来源于此——详见"版本匹配"一节。

补充一句无人值守(headless)的限制:开发/调试阶段我们通常让浏览器"现形"(弹出窗口),这样能看着它跑;生产或 CI 环境里可以加参数让它在后台"无头"运行(headless 模式)。但入门阶段请务必用"有窗口"模式,出了问题看得见、好排查。无人值守模式也是要真实安装 Chrome 的,别以为 headless 就能免装浏览器。


环境准备第二步:安装 Python 运行时

前面定好了用 Python 写脚本,那电脑上就得先有"解释并运行 Python 代码"的那个东西,我们叫它 Python 运行时。装它的正版途径只有一个:官网 python.org。

找到官网、进入下载页

在搜索引擎搜 python,认准带"官网/官方"标识、域名是 python.org 的结果。这里有个所有安装教程都会强调的点:下载安装软件,最靠谱的永远是去官网,不要去那种搜出来排在前面、标着"广告"字样的第三方站点——那些往往是捆绑安装器,装完一堆你没要的东西。

进官网后找 Download for Windows 这个入口。Python 版本在持续更新,你看到的版本号不一定和我写这篇时一模一样(比如 3.10、3.11、3.12……),这完全不影响学习使用。只要认准 Python 3 系列即可。这里补一句背景:Python 分 3 系列和 2 系列,语法有差异,2 系列已经停止维护多年,课堂按 3 系列展开;如果你毕业进公司遇到很老的旧项目还在用 Python 2,记住"两个系列的语法略有出入"就行,本教程全部按 Python 3。

下载完成会得到一个 python-xxx.exe 安装包。

双击安装,勾选关键选项

双击安装包,会进入安装向导。这一步有两个必须做对的动作:

  1. 勾选 Add Python to PATH(把 Python 加入 PATH)。下面整节、以及后面装 pip、配驱动,全都绕不开这个选项。这是新手第一座大坑,务必勾上。
  2. 记牢你的安装目录,Python 就装在这里,最后一步会看到 python.exe 就对了。

选好路径、勾好 Add python.exe to PATH 之后,点 Install Now(立即安装),稍等片刻不报错就是装好了。

验证:跑一个 hello world

装好后,我们验证一下。打开命令行(Windows 下按 Win 键输入 cmd 回车即可),依次输入下面的命令:

# 查看已安装的 Python 版本,能打印出 3.x.x 就说明 Python 装好且被系统找到了
python --version
 
# 进入 Python 交互式解释器(控制台程序),在里面可以直接敲 Python 代码
python

需要先把"交互式解释器"这个概念对准:装完 Python 后,最关键的是安装目录里那个 python.exe,以后运行一切 Python 程序都靠它。在命令行直接输入 python 回车,就会启动一个叫"交互式解释器"的控制台程序,它长这样——提示符变成 >>>,你可以直接往里面输入 Python 代码,敲回车立刻出结果。比如:

# 在 >>> 提示符下输入这行,按回车
print('hello')

如果屏幕上打印出 hello,恭喜,你的 Python 运行时已经可以用了。这里再叮嘱一句所有编程课都会啰嗦的老话:代码里的括号 () 和引号 ' 必须用英文半角符号,千万不要写成中文全角标点(()‘’)。 编程语言从设计上就不认中文字符,写错一个引号,代码立刻报错,而且报错信息对新手极不友好。

思考题:装 Python 的时候,那个 Add Python to PATH 到底是干嘛的?

【思考题 2】 我问你:为什么偏偏要勾选 Add Python to PATH?如果不勾,会有什么后果?

【答案详解】 PATH 是 Windows 的一个系统环境变量,它保存着一串"可执行程序的目录"。你在命令行输入一个命令(比如 python)时,系统会按顺序去 PATH 里列出的这些目录里找对应的 .exe,找到就运行,找不到就报"不是内部或外部命令"。勾选该选项,本质就是把 Python 的安装目录(里面有 python.exe、pip.exe)追加进 PATH,于是你在任意目录敲 python、pip,系统都能找到它们。如果不勾,最直接的后果就是:你在命令行敲 python 会报"'python' 不是内部或外部命令"——明明装了却用不了,得每次用完整路径 C:\你的安装目录\python.exe 才能调,极其折磨。这也是"版本匹配/环境变量"这类坑里最常见的一种。补救办法我们放到最后"常见坑"一节,那里会教你怎么手动把路径加进 PATH。


环境准备第三步:安装开发工具 PyCharm

交互式解释器只适合敲一两句话练手,真正写一个脚本(比如我们最后的 first_test.py)还是需要一个"编辑器/开发环境",我们称它为 IDE(Integrated Development Environment,集成开发环境)。Selenium 这套的黄金搭档选择一个老牌工具:PyCharm,它由 JetBrains 公司出品。

找到官网、认清版本

官网是 jetbrains.com,认准这个域名(它的搜索结果是会直接标明"官网"的,认域名最稳)。进官网后先别急着点正中央那个醒目的下载按钮——把页面拖到最下面,找到 Tools / PyCharm 相关的下载入口。因为 PyCharm 分三个版本,要看清再下载:

版本是否收费一句话特点我们的选择
专业版 Professional收费功能最全,前端/数据库等功能强大不强求
社区版 Community免费纯 Python 开发完全够用推荐(白嫖)
教育版 Educational免费但有门槛功能近专业版,但要凭 edu 教育邮箱去官网申请有 edu 邮箱可试

课堂用免费的**社区版(Community)**就绰绰有余了。下载完成会得到一个 pycharm-community-xxx.exe。

安装与基本设置

双击安装。路径可选默认,也可以自定义。安装向导里有一个值得勾的选项——"把 PyCharm 加进右键菜单,让任意目录右键就能 'Open Folder as PyCharm Project'",建议勾上,以后打开项目会非常方便。装完不报错即成功。

装好后先做点对眼的设置:设置字体大小。PyCharm 默认字体偏小,盯久了眼睛累。菜单 File -> Settings -> Editor -> Font(界面汉化后是"文件->设置->编辑器->字体"),把 Size(字号,数字越大字越大)和 Line height(行高,数字越大两行间距越大)适当调大。这一步纯粹是体验优化,别漏了,它直接决定你后面敲代码的舒适度。

在 PyCharm 里跑通第一个 Python 文件

我们不用命令行跑了,让 PyCharm 正式登场:

  1. 打开 PyCharm,点 New Project(新建项目);
  2. 选好项目存放的路径,并在解释器一栏确认使用的是我们刚装好的 Python(PyCharm 一般会自动识别并选用系统 Python,认准即可);
  3. 在项目里新建一个 Python 文件,比如叫 hello.py;
  4. 写入一行 print("hello from pycharm");
  5. 右键文件,选择 Run 'hello'(运行 hello)——编辑器下方出现控制台输出,就说明整条链路(PyCharm + Python + 项目路径)打通了。

最后这一步"右键选中运行"是 PyCharm 特有的运行方式,也意味着后续我们构建的每一个自动化脚本都能这样一键跑起来。


认识 pip:Python 的"应用商店"

在装 Selenium 之前,我们必须先认识一个叫 pip 的东西,它是 Python 内置的包管理器。什么是包管理器?打个比方:它就像你手机里的"应用商店"——pip 负责把第三方写的代码库(在 Python 界叫"包/库",比如我们马上要用的 selenium)帮你下载、安装到电脑里并做好登记。你不需要手动去网上把别人的代码打包下载再解压到某个目录,一句命令,全搞定。

这些"第三方库"从哪来?为了统一保管,Python 官方建了一个网站叫 PyPI(Python Package Index,Python 包索引),网址是 https://pypi.org/。Python 界的高手们写好一个库,会申请把它上传到 PyPI 上,然后全世界的人都能用 pip 一条命令把它拉下来。机制上,pip 就是一个可执行程序,和 python.exe 一起待在 Python 安装目录里——这就是为什么前面反复强调"安装时勾选 Add Python to PATH":不勾,不仅 python 找不到,连 pip 也找不到。

验证 pip 是否就绪,在命令行输入:

# 单独输入 pip 并回车,如果打印出一大段"Usage/Commands"帮助信息,说明 pip 已经就绪
pip

如果你当初勾选了 Add Python to PATH,那么 pip 是默认可用的。如果这一步你就栽了,报"'pip' 不是内部或外部命令",别慌,这正是我们要在"常见坑"一节修的第一个问题——通常根源就是 PATH 没配上。

小结:pip = Python 内置的"应用商店",联网从 PyPI 拉第三方库;它依赖 PATH 配好才能用。


环境准备第四步:安装 Selenium 框架本身

现在进入正题,装"遥控器手柄"——Selenium 客户端库。用 pip 一句话就能装:

# 用 pip 安装 selenium 库(不指定版本时,pip 会安装最新稳定版)
pip install selenium

关于版本,这里有个校训级的注意点,我要拿尺子量着叮嘱:

  • Selenium 的版本非常多、迭代很快。课堂和本教程以 Selenium 4 系列为中心;而你看到网上大量旧教程写的是 Selenium 3、甚至 2。Selenium 3 和 4 的 API 有差异(4 代大量改用 W3C 标准、部分写法和导入路径变化),直接照抄旧代码可能报错。
  • 如果你需要和课件版本保持一致,可以锁版本安装,比如官方推荐的经典版本写法:
# 指定安装 4.x 中的某个具体版本,保证和课程一致(示例使用 4.0.0)
pip install selenium==4.0.0

看到 == 了吗?这是 pip 里"锁定精确版本"的写法。如果你对版本不确定,直接 pip install selenium 装最新稳定版也行,这篇的写法在 Selenium 4 全系列都适用。

装完怎么确认装成功?在交互式解释器或脚本里验证:

# 导入 selenium 模块;能成功 import 不报错,就说明装好了
import selenium
 
# 打印出版本号,进一步确认
print(selenium.__version__)

思考题:pip install selenium 和 pip install selenium==4.0.0 有啥区别?什么时候该用哪个?

【思考题 3】 同样是安装 selenium,一个是"不带版本号",一个是"带 ==4.0.0",二者行为有何不同?各自适合什么坑?

【答案详解】 不带版本号(pip install selenium),pip 会从 PyPI 去拉取当前最新稳定版;它适合"我无所谓精确版本,要最新就好"。带 == 版本号(pip install selenium==4.0.0)则是锁定版本,pip 只装那个精确的版本(装过就直接用,没装过就装它)。它适合两种场景:一是课程/团队约定统一版本,大家保持一致,避免"你 4.0 我 5.0,代码行为对不上"的分裂;二是你的脚本是照着某版本写的,锁定后就不会因为库升级导致 API 变化而出错。一句话建议:平时学习装最新没问题;一旦你的脚本定了型、或者要跟课件走、要和队友对齐,就锁定版本。


浏览器驱动与版本匹配:最劝退的一关

脚本写好之前,有一座几乎人人都会翻船的大山,必须先翻过去——浏览器驱动。这里要同时讲清两个名词:驱动是什么,以及那著名的"驱动和浏览器版本必须匹配"的魔咒。

什么是驱动(Driver)

我们在"WebDriver"一节画过链路:脚本 → 客户端库 → 浏览器驱动 → 浏览器。驱动(Driver)是一个由浏览器厂商提供的小型可执行程序,比如 Chrome 的驱动叫 ChromeDriver(chromedriver)、Edge 的叫 msedgedriver、Firefox 的叫 geckodriver。它的职责是:监听来自客户端库的 WebDriver 协议请求,把它们"翻译"成浏览器听得懂的内部指令,并回报结果。没有驱动,你的脚本就没有"翻译官",喊破嗓子浏览器也听不懂。

上一节我们装了 selenium 客户端库,那只是拿到了"遥控器手柄";驱动相当于"翻译机",二者缺一不可。所以环境搭建其实有两条线:一条装"语言+框架",一条装"驱动"。

致命魔咒:驱动版本必须匹配浏览器主版本

这是新手拜倒最多、也最掉头发的一处:chromedriver 的版本要和你的 Chrome 浏览器的主版本号一致(至少主版本一致)。 什么叫主版本号?Chrome 的版本号形如 120.0.6099.109,其中第一个数字 120 就是主版本。chromedriver 也有自己的版本号,二者必须"对上"——实践上要求主版本一致,最严格时可以要求副版本也一致。

为什么必须匹配?因为驱动和浏览器在底层有一套私有的、非公开的通信细节,浏览器厂商在升级浏览器时可能改动这些细节,老驱动去驱动新浏览器(或反过来)就"鸡同鸭讲",典型表现是:驱动能打开浏览器,但一执行操作就报 session not created 之类让人摸不着头脑的错;或者干脆 message: invalid argument 一堆报错。

那么问题来了:Chrome 会自动更新。今天你装了个 Chromedriver 120,下个月 Chrome 悄悄升到 121,你什么都没动,可之前的脚本突然跑不动了。这就是"版本匹配"为什么是个持续存在的、最折磨人的坑——它不是一次性的,是长期维护动作。

三套解决驱动匹配问题的方案

解决"驱动匹配浏览器版本"这件事,业界有从"纯手动"到"全自动"的三套方案,由旧到新如下:

方案一(最原始):手动下载对应版本的 chromedriver。 去 Chrome for Testing 或旧版 chromedriver 下载站,找到和你 Chrome 主版本一致的 chromedriver.exe,解压出来放到一个你能记住的目录,然后在代码里用 Service 指定它的路径。麻烦点:每次 Chrome 升级,你都得跟着换一次驱动,纯人工维护,容易忘。

方案二(半自动,也是本教程主推):用 webdriver-manager 自动下载。 它是个 Python 库,会在你运行脚本的那一刻自动检测你电脑上 Chrome 的版本、自动去下载匹配的驱动并缓存起来,然后直接交给 Selenium 用。从此你几乎不用再管驱动版本,最大程度绕开"版本匹配"魔咒。装它:

# 用 pip 安装 webdriver-manager,它是专门帮我们自动管理浏览器驱动的小工具
pip install webdriver-manager

方案三(Selenium 4.6 之后内置的 Selenium Manager,真正免安装): Selenium 4.6+ 已经内建了一个叫 Selenium Manager 的组件,在你用默认方式创建浏览器驱动时,它会自动探测浏览器版本、自动下载并缓存匹配的驱动——也就是说,如果你用的是较新的 Selenium 4,装了最新版 Chrome,甚至可以不装 webdriver-manager、不手动放驱动,直接让 Selenium 自己解决。这是现在最省心的路径。不过为了教学稳定、也为了你能看清"驱动从哪来、去哪了",本教程两种都会让你见到:WebDriver 一节用 webdriver-manager 显式装,让你既有把握也有掌控;同时我会告诉你"Selenium 4.6+ 其实能自动搞定"这个事实,方便你在工程里用更省心的写法。

需要手动配驱动路径时怎么办

少数场景下(比如公司内网无法让库联网下载驱动),你必须手动下载驱动并告诉 Selenium 驱动在哪。以 Windows + Chrome 为例,命令大致长这样(只是演示,本教程主流程用 webdriver-manager,不必照抄):

# 手动把下载好的 chromedriver.exe 解压,并记下它的完整路径,例如:
#   C:\drivers\chromedriver.exe
# 然后在代码里用 ChromeService(路径) 指定它,Selenium 就会用这个驱动

这段对应 selenium.webdriver.chrome.service 里的 ChromeService——它负责告诉 Selenium"驱动文件在哪、怎么把它跑起来"。webdriver-manager 的 ChromeDriverManager().install() 这个方法,干的就是帮我们拿到这样一个正确的驱动路径,交给了 ChromeService。

小结:驱动 = 浏览器厂商给的"翻译机",缺了它脚本没法和浏览器对话;它最大的坑是"必须和浏览器主版本匹配",而 Chrome 会自己升级,所以最佳实践是用 webdriver-manager 或 Selenium Manager 让"下载匹配驱动"这件事自动化,别手动维护。


第一个自动化脚本

环境四条线(浏览器、Python、PyCharm 与 pip、Selenium 与驱动)都通了,接下来写出第一个真正跑起来的自动化脚本。我们把课堂的经典示例搬过来并逐行讲透——让脚本打开百度,在搜索框输入"迪丽热巴",点"百度一下",然后关掉浏览器。

from selenium import webdriver                        # 导入 webdriver 模块,它是所有浏览器控制的入口
from selenium.webdriver.chrome.service import Service as ChromeService  # 导入 ChromeService,用于指定 Chrome 驱动
from selenium.webdriver.common.by import By           # 导入 By,元素定位时用它的属性指定"按什么方式找元素"
from webdriver_manager.chrome import ChromeDriverManager                   # 导入 webdriver-manager,用于自动获取匹配的驱动
 
# 1. 创建驱动对象:用 webdriver-manager 自动下载/获取匹配当前浏览器版本的 Chrome 驱动,
#    交给 ChromeService,再传给 webdriver.Chrome()。这一步会真正"打开一个浏览器窗口"。
driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()))
 
# 2. 让浏览器打开百度首页,get() 方法就是"当前页面跳转到指定网址"
driver.get("https://www.baidu.com")
 
# 3. 元素定位 + 输入:find_element 在页面 DOM 树里找到元素,send_keys 向输入框输入文字。
#    这里用 CSS 选择器按 input 的 id="kw" 找到搜索框(百度搜索框的 id 正是 kw)
driver.find_element(By.CSS_SELECTOR, "#kw").send_keys("迪丽热巴")
 
# 4. 找到"百度一下"按钮并点击:百度"百度一下"按钮的 id 为 su,click() 等价于鼠标左键点击
driver.find_element(By.CSS_SELECTOR, "#su").click()
 
# 5. 关闭浏览器:quit() 关闭整个浏览器会话(比 close() 更彻底)
driver.quit()

把这段存成 first_test.py,在 PyCharm 里右键 Run 'first_test',如果你的环境搭得没问题,你几乎能看到:一个 Chrome 窗口自动弹出 → 自动跳转百度 → 自动输入 → 自动点击 → 弹出结果页 → 自动关闭。这就是你的第一个 Selenium 自动化脚本。

逐行的"为什么"

  • webdriver.Chrome(...):这是"创建驱动对象"的入口,它代表"一个被我们控制的 Chrome"。传 service=ChromeService(ChromeDriverManager().install()) 是告诉它"去自动获取匹配版本的驱动并用它启动浏览器"。Selenium 4 的写法。
  • driver.get(url):方法名 get,"让浏览器访问这个网址"。
  • driver.find_element(By.CSS_SELECTOR, "#kw"):这是元素定位的标准姿势。要找搜索框,就得先告诉程序"怎么找、按什么找"。By.CSS_SELECTOR 表示"用 CSS 选择器的方式找",#kw 就是 CSS 选择器写法,表示"取 id 为 kw 的元素"(# 前缀代表 id)。百度搜索输入框的 HTML 正好是 <input id="kw" ...>,所以这一行就定位到了它。
  • .send_keys("..."):往刚定位到的元素里"敲入"文字,等价于你键盘打字。
  • .click():对元素做一次鼠标左键点击。定位到"百度一下"按钮(id 为 su)后点击。
  • driver.quit():结束会话、关闭浏览器。注意它和 close() 的区别:quit() 关闭整个浏览器实例/所有窗口,是标准收尾动作;close() 只关当前窗口。脚本通常用 quit()。

关于"如何知道百度搜索框的 id 是 kw、按钮是 su"——这是新手最常问的:"你凭什么知道 #kw?"答案:靠 F12 开发者工具。打开页面按 F12,点左上角那个箭头图标,再去页面上点搜索框,就会在 Elements 面板高亮出对应的 HTML 标签,你就能看到它的 id、class 等属性,据此写出定位表达式。这属于"元素定位"的进阶内容,入门先会用即可。

一个非常现实的提醒:这个脚本依赖"百度页面当前长这样"。如果哪天百度改版、把搜索框的 id 改了,这段脚本会定位不到元素而报错。这恰恰说明了 UI 自动化的天然脆弱性——这也是为什么工程上要把定位写得更健壮(用更稳定的属性、或配置化管理),入门阶段我们先跑通。

webdriver-manager 装没装的检查

如果你脚本第一行 from webdriver_manager.chrome import ChromeDriverManager 就报 ModuleNotFoundError,说明 webdriver-manager 没装上,回"环境准备"用 pip install webdriver-manager 装一次。同样,from selenium import webdriver 报错就是 selenium 没装。这俩是前几节埋下的地基,缺一不可。

思考题:元素定位里,By.CSS_SELECTOR 和 "#kw" 分别是什么?如果改成 By.ID 改写?

【思考题 4】 代码里 driver.find_element(By.CSS_SELECTOR, "#kw") 这一行,By.CSS_SELECTOR 和 "#kw" 各自表达什么?如果我想"按 id 找",该写成什么样,效果一样吗?

【答案详解】 拆开看:By.CSS_SELECTOR 是一个"定位策略"常量,表示"使用 CSS 选择器的语法去匹配元素";"#kw" 则是具体的定位表达式(pattern),#kw 是 CSS 语法里"选取 id 为 kw 的元素"的写法,# 表示 id。二者合起来的意思是"用 CSS 选择器 #kw 去页面里找元素"。它们分别回答"用什么方式找"和"用什么表达式找"。如果改用"按 id 找",可以直接写成 By.ID 加 "kw":driver.find_element(By.ID, "kw")。因为元素定位的本质是"给一个定位方式+一个匹配值",By.ID, "kw" 与 By.CSS_SELECTOR, "#kw" 在这条语句里定位到的是同一个元素(都是 id 为 kw 的搜索框),效果一致。区别只在表达风格:By.ID 更直白,By.CSS_SELECTOR 更通用(能表达 id/class/属性/层级等组合)。入门先掌握这条"找方式+找什么"的框架即可。


常见启动坑与排查手册

环境搭好、脚本写好了,但很多人第一次跑还是会被各种报错劝退。这一节我们把最常见的坑集中"点兵",每一个都讲清症状、根因和处置。

坑 1:python 或 pip 不是内部或外部命令

症状:在命令行敲 pip 或 python,系统提示"'pip' 不是内部或外部命令,也不是可运行的程序或批处理文件"。 根因:没把 Python 的安装目录加进 PATH 环境变量(大概率是安装时没勾 Add Python to PATH,或勾了但环境变量没生效)。 处置:有两条路。最省事的是卸载重装 Python,这次务必勾上 Add Python to PATH——几乎是零成本的根治办法。如果你想手工修,也可以手动把 Python 安装目录(以及其下的 Scripts 目录,pip 就在那里)追加到 PATH:系统属性 -> 环境变量 -> 系统变量里的 Path -> 编辑 -> 新建 -> 粘贴你的 Python 目录,保存后重开命令行再试(环境变量改动对已开窗口不生效)。这里必须要提一句:手工加 PATH 容易因为加错目录、或配置了错误的变量名而引入新问题,所以新手我优先建议"重装勾选"这条路,它最不容易出错。

坑 2:ModuleNotFoundError: No module named 'selenium'(或 webdriver_manager)

症状:脚本第一行 import 就报找不到模块。 根因:selenium 或 webdriver-manager 没安装,或者装到了别的 Python 环境里。新手常犯:命令行里 pip install selenium 装到了 A,但 PyCharm 用的解释器是 B(或虚拟环境),两者不互通。 处置:先 pip list(列出本环境已装的第三方库)确认装没装;确认没装就 pip install selenium webdriver-manager。重点:一定在 PyCharm 的 File -> Settings -> Project -> Python Interpreter 里看当前项目用哪个解释器,确保它就是你 pip 装的同一个 Python。这是"环境分裂"的经典坑。

坑 3:SessionNotCreatedException / invalid argument 等启动即崩

症状:能弹浏览器,但随即报 session not created、invalid argument、version 之类一大串错。 根因:驱动与浏览器版本不匹配的典型响应。比如你的 Chrome 是 121 而驱动是 120。 处置:首选方案就是让工具自动匹配——确保用了 webdriver-manager(本教程主推)或 Selenium 4.6+ 的 Selenium Manager;这样驱动会被自动按浏览器当前版本拉取,从源头消除匹配问题。如果还在手动维护驱动,就去更新成与浏览器主版本一致的驱动。偶尔还要考虑:Chrome 刚更新、而驱动缓存里还是旧驱动,可清理 webdriver-manager 的缓存目录(Linux/mac 在 ~/.wdm、Windows 在用户目录下)后重跑。

坑 4:浏览器没装上、或装的是"盗版/精简版"浏览器

症状:一切报错排除了,可驱动还是连不上浏览器,或者浏览器闪退打不开。 根因:机器上没有装对应的浏览器,或装的浏览器不是官网正版、底层组件被魔改/精简。 处置:去官网(www.google.com/chrome 等)下载正版安装并安装。这是我们在"环境准备第一步"就埋的伏笔——很多疑难杂症最后都归结到这里。

坑 5:页面元素定位不到(NoSuchElementException)

症状:浏览器打开了、网址跳转了,但 find_element 一步报"找不到元素"。 根因:要么定位表达式写错了(id 变了、不叫这个),要么页面还没加载完就去定位了(元素在、但异步渲染没完成),于是没找到。 处置:先在浏览器 F12 里确认真实 id/属性再改表达式;若确定是加载时序问题,给定位加"显式等待"(WebDriverWait 配 expected_conditions,Selenium 4 的标准做法),让脚本等到元素出现再操作。等待机制属于进阶,入门阶段知道"找不到元素先查定位、再想等待"即可。

坑 6:headless(无头)模式"悄悄失败"

症状:用无人值守模式运行时,什么都没弹、好像什么都没发生,也难定位问题。 根因:headless 模式下浏览器不弹窗,出错时黑盒难查。 处置:入门阶段一律用有窗口模式调试,跑通了再说无头;确实需要 headless 时,加 add_argument("--headless=new") 这类参数(写法随 Selenium/Chrome 版本略有差异),用于 CI 或服务器场景。无人值守限制的本质是"它仍然是真实的浏览器,不是脱离安装的魔法"。

排查铁律:报错永远从"最底层的依赖"往前查——先确认 Python/pip 通(坑1)→ 再确认库装对(坑2)→ 再确认浏览器与驱动(坑3、坑4)→ 最后才怀疑脚本本身(坑5)。顺序对了,很多问题秒解。


本期自测:把读过的变你的

写博客不能"看完就完"。下面几道自测题,请先独立做,再看详解答案校对。每题都从概念和应用两个角度设问,覆盖本篇核心。

自测 1:一句话说清楚 Selenium、WebDriver、浏览器驱动(chromedriver) 三者各自是什么、在调用链上处于什么位置?

【详解答案】 Selenium 是整套浏览器自动化工具与客户端库的总称;WebDriver 是客户端库与浏览器之间"遥控对话"所依赖的统一协议标准;浏览器驱动(chromedriver)是浏览器厂商提供的、把 WebDriver 协议指令翻译成浏览器原生动作的独立可执行程序。调用链自上游到下游是:Selenium 客户端库 → WebDriver 协议 → 浏览器驱动 → 浏览器。三者缺一,链路就断。

自测 2:为什么 chromium 的驱动和浏览器要"版本匹配"?主版本不一致会怎样?

【详解答案】 因为驱动与浏览器之间依赖浏览器厂商私有、非公开、随版本可能改变的底层通信细节;驱动必须"认识"对应版本的浏览器。主版本不一致时,二者"对话"错位,典型表现是脚本启动浏览器后立刻报 session not created / invalid argument 或一操作就崩。由于 Chrome 会自动升级,这个问题会反复出现,因此业界标准做法是用 webdriver-manager 或 Selenium Manager 在运行时自动拉取与当前浏览器匹配的驱动。

自测 3:安装 Python 时那个 Add Python to PATH 不勾会怎样?遇到该问题有哪两种处理方式,各自适用的时机?

【详解答案】 不勾的话,python、pip 都不会被系统在命令行里自动找到,输入会报"不是内部或外部命令"。处置有两条:一是卸载重装并在向导里勾上该选项(最简单、最适合新手,几乎根治);二是手动把 Python 目录(含 Scripts 下的 pip)追加进系统环境变量 Path 并重开命令行(适合不想重装、或二次修复的场景,但手工改环境变量要小心加错)。原则:新手优先重装勾选,别手工折腾 PATH。

自测 4:driver.quit() 和 driver.close() 有何区别?为什么脚本通常用 quit()?

【详解答案】 close() 只关闭当前浏览器窗口(driver 所指向的标签页),但整个浏览器进程(及其他窗口)可能还留着;quit() 则结束整个 WebDriver 会话、关闭所有由它驱动的窗口并释放驱动资源,是标准且彻底的收尾。自动化脚本用 quit(),既保证浏览器被完整退出、也避免残留进程或没能释放驱动导致的"端口被占""进程残留"等二次问题。

自测 5:写出用 By.ID 定位百度搜索框(id 为 kw)并输入的写法,说明它与课堂示例里 By.CSS_SELECTOR, "#kw" 的异同。

【详解答案】 写法是 driver.find_element(By.ID, "kw").send_keys("迪丽热巴")。它与 By.CSS_SELECTOR, "#kw" 在"定位策略"上不同——前者声明按 id 定位、后者声明按 CSS 选择器定位;但两者最终命中的是同一个元素(id 为 kw 的输入框)。区别在于表达粒度:By.ID 直白、语义明确,By.CSS_SELECTOR 更通用、能表达更复杂的定位条件(组合 id/class/属性/层级)。入门阶段记住"找法 + 找什么"的框架即可,两者等价可用。


自然收尾:从"能跑"到"会跑"

到这里,我们已经把"安装 Selenium 自动化"这条从零到一的路完整走了一遍:先弄懂了 Selenium 是什么、为什么 UI 自动化值得学,讲清了 WebDriver 作为中间协议的意义;然后一句一句把环境搭起来——装正版浏览器、装 Python 并勾选 PATH、装 PyCharm、认识 pip、装上 selenium 库与 webdriver-manager 驱动管理;接着用 webdriver-manager 绕开"驱动与浏览器版本匹配"这道天堑,最终写出了第一个能真正开浏览器、找元素、输入、点击、关窗口的脚本,并备好了一整册"启动坑"的排查手册。

你可以回头自查一下这条链路是不是全通了:浏览器在官网装的(↔ 坑4)→ Python 装了且 PATH 勾了(↔ 坑1)→ PyCharm 里解释器选对了(↔ 坑2)→ selenium、webdriver-manager 装进同一个环境(↔ 坑2)→ 跑脚本时驱动自动匹配版本(↔ 坑3)→ 有窗口模式先调试(↔ 坑5、坑6)。把这六条刻进记忆,你后面的路会顺很多。

如果非要把这篇浓缩成一件事:UI 自动化的地基不是"会写代码",而是"让浏览器能被程序稳定地打开和操控"——而这恰恰就是版本匹配、PATH 这些"环境杂事"的地盘。这些看似琐碎的环境问题,恰恰是区分"看过教程"和"真能落地"的分水岭。

下一篇,我们顺着第一个脚本往下走,进入 Selenium 真正的核心世界:元素定位与页面交互——从 F12 开发者工具看穿页面结构,到 id / CSS 选择器 / XPath 的选型取舍,再到如何用显式等待驯服"异步加载"。到那时候,你写的就不是"能跑"的脚本,而是"跑得稳、改得动"的真自动化了。准备好了吗?