做Web自动化的人都知道,ChromeDriver下载地址看起来不是个事,但真正操作起来,版本对不上、路径配错、环境变量没生效,每一个坑都能卡住你半天。这篇文章不绕弯子,直接讲清楚ChromeDriver到哪里下、怎么下、下完怎么配,以及真正运行起来之后你会遇到的各种报错怎么处理。内容适合刚入门Selenium的新手,也适合已经写了不少脚本、但每次换电脑都要重新折腾一遍环境的熟手。核心先记住一句话:ChromeDriver的版本必须和Chrome浏览器的版本精确对应,主版本号不一致,一切免谈。
1. 版本匹配逻辑与下载前的准备
1.1 为什么ChromeDriver必须和Chrome版本一致
ChromeDriver本质上是一个独立运行的中间服务,它接收你的自动化代码发来的命令,再把命令翻译成浏览器能理解的操作,同时把浏览器里的页面状态回传给你。这个翻译过程依赖一套持续变化的内部协议,Chrome每一次大版本升级,协议都会有调整。如果驱动和浏览器版本差太多,两边说的话对不上,浏览器要么拒绝启动,要么启动后完全无响应。
我见过最典型的例子:有人拿着老教程里的驱动下载地址,下了一个版本很旧的驱动,然后打开最新版Chrome,启动瞬间就报session not created,连日志都看不懂。其实原因很简单,就像你用一把旧钥匙去开一把新锁,齿痕差一毫米都转不动。ChromeDriver的版本匹配要求是指纹级的,不是“差不多能用”就行。
1.2 查看浏览器版本号的三种姿势
在下载驱动之前,第一步永远是确定当前浏览器是什么版本。
第一种方式:打开Chrome浏览器,在地址栏输入chrome://version,直接回车。页面顶部会显示完整的版本号,比如114.0.5735.110。这个页面里还能看到浏览器版本存放路径和协议版本,对排查问题很有帮助。
第二种方式:点击浏览器右上角的“三个点”菜单,找到“帮助”,再点“关于Chrome”。弹窗里会显示版本号,如果有更新还会提示重启浏览器。
第三种方式:如果是自动化脚本里要动态获取,可以用Python执行chrome --version命令,但Windows上Chrome的默认安装路径经常带空格,命令得写成"C:\Program Files\Google\Chrome\Application\chrome.exe" --version,这样也能拿到版本号。
拿到版本号之后,只需要记前两位或前三位主版本号。比如114.0.5735.110,主版本号是114。下载ChromeDriver时,要找对应114开头的驱动,后面的小数位可以不完全相等,但主版本一定不能差。
注意:如果浏览器开了自动更新,今天看是114,过几天可能就变115了,所以驱动下载后最好把浏览器自动更新关掉,或者把驱动版本和浏览器版本都固定在你项目的环境说明里。
2. 从官方渠道获取ChromeDriver的正确姿势
2.1 官方发布页的页面结构
ChromeDriver的官方下载页面其实是一个很朴素的目录列表,没有花哨的界面。第一次打开的人往往一脸懵,不知道点哪里。
页面顶部通常有“Latest stable release”的提示,下面跟着一串版本号,比如114.0.5735.90。这个数字就是当前最新的稳定版驱动版本。接着往下翻,会看到按版本号排列的文件夹,每个文件夹名就是主版本号。点击进入对应文件夹,里面才是各个操作系统对应的压缩包。
这里有个容易被坑的点:页面上可能会有多个版本号很接近的文件夹,比如114.0.5735.90和114.0.5735.110,它们的区别在于修复版本不同。如果你的浏览器是114.0.5735.110,理论上驱动用114.0.5735.90或114.0.5735.110都能正常跑,因为主版本都是114。但为了省事,建议直接选和浏览器小版本差距最小的那个。
2.2 按系统平台选择正确的压缩包
进入版本文件夹后,你会看到类似这样的文件列表:
chromedriver_win32.zipchromedriver_mac64.zipchromedriver_mac64_m1.zipchromedriver_linux64.zip
选择规则很简单:Windows不管32位还是64位系统,都下载win32这个包,因为ChromeDriver的Windows版是32位兼容的;macOS用户如果用的是M1或M2芯片,记得选mac64_m1;Linux服务器一般选linux64,但要注意服务器系统架构,如果是ARM架构,得找对应的linux_aarch64版本。
下载后一定要做一步操作:解压前先右键压缩包,在属性里看有没有“解除锁定”选项,如果有就勾上再解压。Windows系统经常会把下载的zip文件标记为“来自其他计算机”,这种文件解压出来的exe可能被杀毒软件直接拦截,或者运行时报“无法验证发布者”。
3. 下载之后的解压与环境变量配置
3.1 文件放哪里最省心
很多人下完驱动把zip解压在当前下载目录,然后代码里写死一个绝对路径。这样也能用,但一旦路径里有空格,或者临时清理了下载目录,脚本就废了。我更建议单独建一个专门放驱动文件的目录,比如C:\webdrivers\或者~/webdrivers/,把解压出来的chromedriver(Windows下是chromedriver.exe)放进去。
目录里最好只放驱动文件,不要混放其他东西。因为接下来要配PATH环境变量,配的是整个目录,如果目录里的文件太杂,将来排查问题分不清谁是谁。另外,目录名不要用中文,有些老版本工具对中文路径支持不好,报错信息会非常莫名其妙。
3.2 Windows环境变量配置全流程
Windows配置环境变量是新手最容易卡壳的地方。具体步骤是:右键“此电脑”选“属性”,点“高级系统设置”,再点“环境变量”。在“用户变量”或“系统变量”中找到Path这一项,双击打开,点“新建”,把C:\webdrivers填进去,然后一路点“确定”。
注意:如果你需要用管理员权限跑自动化脚本,建议配到“系统变量”,否则脚本运行时找不到驱动。配完之后要重开命令行窗口,因为环境变量只在新的进程里生效。验证是否配置成功,打开一个新的命令行窗口,输入chromedriver --version,如果能看到类似ChromeDriver 114.0.5735.90的输出,就说明环境变量没问题。
3.3 macOS和Linux的配置方法
macOS和Linux逻辑一样,都是修改shell配置文件。如果你用的bash,编辑~/.bashrc或~/.bash_profile,在文件末尾加一行:
export PATH="$HOME/webdrivers:$PATH"如果用zsh(macOS默认),就编辑~/.zshrc。保存后执行source ~/.zshrc让配置立即生效,然后输入chromedriver --version验证。
这里有个特别容易忽略的点:macOS上的ChromeDriver是未签名或签名不完整的文件,第一次运行会被Gatekeeper拦下来,提示“无法打开,因为无法验证开发者”。解决方法是右键点击文件,选择“打开”,然后在弹窗里点“打开”绕过一次;或者用xattr -d com.apple.quarantine ~/webdrivers/chromedriver命令删除隔离属性。Linux上没有这个困扰,但要注意文件权限,运行chmod +x ~/webdrivers/chromedriver给执行权限。
4. 用Selenium连接ChromeDriver的完整示例
4.1 最简单的一段自动化代码
环境配好之后,写一段最小验证代码。假设你用的是Python,并且已经装好了Selenium库(pip install selenium)。
from selenium import webdriver from selenium.webdriver.chrome.options import Options options = Options() # 这里可以不手动指定driver路径,因为已经在PATH里 driver = webdriver.Chrome(options=options) driver.get("https://example.com") print(driver.title) driver.quit()运行这段代码,如果浏览器能自动启动并打开页面,说明ChromeDriver下载和配置已经全部成功。如果你不想配置环境变量,也可以把驱动路径直接写在代码里:
driver = webdriver.Chrome(executable_path="/path/to/chromedriver", options=options)注意新版Selenium(4.x以上)的写法变了,executable_path参数已经废弃,改为用Service对象:
from selenium import webdriver from selenium.webdriver.chrome.service import Service service = Service(executable_path="/path/to/chromedriver") driver = webdriver.Chrome(service=service, options=options)4.2 启动参数里藏着的实用配置
真实项目里通常不会只调一个空白页面,常见需求包括:让浏览器不加载图片、忽略证书错误、使用无头模式等。这些都可以通过Options添加参数。
options.add_argument("--headless=new") options.add_argument("--ignore-certificate-errors") options.add_argument("--disable-gpu") options.add_argument("--remote-debugging-port=9222")--remote-debugging-port是ChromeDriver启用的远程调试端口。默认情况下驱动和浏览器通过内部端口通信,端口是随机分配的。手动指定端口后,你可以直接访问localhost:9222/json查看当前所有打开的标签页信息,调试阶段特别方便。不过要注意,如果你同时跑多个自动化脚本,端口就不能写死,否则会冲突。
我在实际项目里还遇到过一种情况:服务器上跑的好好的脚本,移到本地Windows机器上就报“DevToolsActivePort file doesn't exist”。这个问题多半是浏览器启动时没能创建临时用户数据目录导致的。解决方法是给Chrome指定一个独立的用户数据目录:
options.add_argument("--user-data-dir=/tmp/chrome_temp")这个目录会存放浏览器的配置和缓存,不要和日常使用的浏览记录混在一起,否则会互相干扰登录态。
5. 常见问题速查与避坑指南
5.1 报错session not created:大部分是版本问题
这个报错信息长这样:
selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 114 Current browser version is 116.0.1938.69信息已经直说了:驱动支持114,浏览器是116。解决办法只有一个:下载匹配116的驱动,或者把浏览器降回114。不用相信网上那些“禁用自动更新就能兼容”的说法,跨大版本的驱动和浏览器基本没有兼容可能。别在这上面花时间找偏方,直接去官方发布页找对应版本。
5.2 报错cannot find Chrome binary:路径没指定
selenium.common.exceptions.WebDriverException: Message: unknown error: cannot find Chrome binary这种情况一般不是驱动问题,而是ChromeDriver找不到浏览器本体。Windows上往往是因为浏览器没装在默认路径。可以手动指定:
options.binary_location = r"C:\Program Files\Chrome\Application\chrome.exe"Linux上也可以指定,例如:
options.binary_location = "/usr/bin/google-chrome"路径写错的话会继续报错,先确认这个路径下真的有可执行文件。
5.3 报错port already in use:清理残留进程
如果你在脚本里手动指定了调试端口,上次脚本崩溃后,后台进程可能还占着这个端口。启动时就会报:
ERROR: listen EADDRINUSE: address already in use :::9222解决方式很简单:关闭所有Chrome相关进程,包括后台运行的其他Chrome标签页。Windows下可以用任务管理器查看,或者命令行执行taskkill /F /IM chromedriver.exe /IM chrome.exe强制结束。macOS下用pkill -f chromedriver,pkill -f "Google Chrome"。如果还不行,换一个端口重新指定。
5.4 驱动一闪而过或被安全软件拦截
Windows下双击chromedriver.exe闪了一下就消失,这不一定是配置失败。ChromeDriver本身是命令行程序,它启动后会监听端口,但没有交互界面,属于正常现象。真正的问题是杀毒软件经常把chromedriver.exe误判为威胁,直接隔离或拦截。我自己的经验是把webdrivers目录加入安全软件的白名单,然后重新下载一次解压,避免驱动文件被删。
6. 实操心得:那些没人明说的细节
6.1 下载来源别乱用
ChromeDriver的下载地址很容易被各种教程改写,有些博客为了引流会放自己的网盘链接,驱动被二次打包后里面可能夹带私货。我个人的原则是:只从官方发布页下载,哪怕官方页面加载慢一点,都比从网盘下方便快捷得多。识别官方页面的方法很简单,看域名特征和页面风格——官方页面就是一个极简的文件目录,没有任何广告和“下载加速器”按钮。
6.2 版本号写进项目依赖清单
很多团队管理Python依赖用requirements.txt,但没人管驱动版本。这其实是个隐患:两个开发员一个用114驱动,一个用116驱动,代码在同一个仓库,行为却可能不一样。更稳妥的做法是在项目根目录放一个webdriver.txt,写明chrome=114.0.5735.110、chromedriver=114.0.5735.90,甚至把下载链接和安装步骤都写进去。有人接手的时候,照着文件内容就能复现环境。
6.3 自动更新是最大的隐藏坑
Chrome默认自动更新,有时候早上跑好的脚本,下午就报错,查了半天发现浏览器升级了,驱动没跟上。想彻底解决,可以用组策略或企业级配置锁版本,但个人机器做起来麻烦。折中方案是写一个环境检查脚本,启动前用本地命令查浏览器版本,再和手动指定的驱动版本比对,不一致就报错提醒。网上有现成的版本检测接口,但这个方案依赖网络,网络不通时会误报,所以我的做法更简单:在项目启动日志里把两个版本号都打印出来,出问题先看日志。
最后再分享一个我自己常用的技巧:不要只下载最新版驱动,还要在本地保留一份过去几个主版本的驱动压缩包。有时候你接手旧项目,代码里写死了老版本驱动路径,临时去官网翻历史版本,下载页面的目录不少,找起来也花时间。本地备好几份,换项目环境时直接解压就行。我通常按C:\webdrivers\114\chromedriver.exe这种目录结构存放,需要哪个版本就引用哪个,互不干扰。这个习惯帮我省了不少折腾时间,也推荐你试试。