简介:Selenium 3.141.0 的离线安装包,专为因网络波动导致 pip 在线安装频繁中断、或从官网下载源码速度缓慢的 Python 开发者与自动化测试人员准备,有效规避在线安装时的超时与断流问题。压缩包内含完整 Selenium 库源码及配套文件,解压即可安装部署,无需再次在线拉取依赖,免去反复重试或手动修复残缺文件。包体共 104 个文件,结构清晰:核心逻辑集中在 86 个 Python 模块中,覆盖 WebDriver 初始化、元素定位、事件触发、显式等待等常用自动化操作;同时包含与浏览器驱动通信所需的 .js 脚本、.so 扩展,以及 .pkg-info、.json、.cfg 等安装元数据与 LICENSE、CHANGES 说明文件,保证安装过程完整可靠。整个压缩包仅 905KB,轻巧便携,无论初学入门还是项目二次开发都很方便。目前已有 2130 人学习下载,适用于快速搭建 Selenium 开发环境,支撑 Web 自动化测试、动态页面爬虫、表单批量填写、页面截图等典型场景,尤其适合内网或弱网环境下的开发者离线部署使用。
1. Selenium 3.141.0:为什么我还在装这个「上一代」版本
如果你现在打开终端直接执行pip install selenium,多半会装到 4.x 甚至更新的版本,但很多公司的老系统、爬虫脚本、自动化测试框架里躺着的那份依赖清单,写的却是selenium==3.141.0。这个版本是 Selenium 3.x 系列最后的稳定版,之后整个项目跳到 4.x,API、驱动管理方式、定位策略全部换了一套。我见过不少开发者把环境从零搭起来,一条pip install selenium装完,代码一跑,报错信息里全是新版才有的概念,回头一看,原来 3.141.0 和 4.x 根本不是一回事。
这套环境本身不复杂,真正麻烦的是三件事:Python 版本怎么选、浏览器驱动怎么配、版本之间怎么对齐。装不好,轻则WebDriverException,重则浏览器窗口弹不出来,整个下午耗在某个驱动路径上。这篇文章就是把我自己装 Selenium 3.141.0 的过程完整记录下来,从 Python 环境到浏览器驱动,再到排错和验证,照着走一遍就能跑通。适合正在维护老脚本、接手旧测试框架,或者因为项目原因必须锁死 3.141.0 版本的开发者。
2. 安装前置:把 Python 和 pip 环境理清楚
2.1 Python 版本选择:3.8 是 3.141.0 最省心的搭档
Selenium 3.141.0 发布于 2018 年底,官方声明支持的 Python 版本是 2.7、3.5 到 3.7。但实际在真实环境里,我用 Python 3.8 跑过大量基于 3.141.0 的脚本,表现稳定,没有任何兼容性问题。到了 Python 3.9、3.10,3.141.0 依然能 import 能跑,但会偶尔冒出来一些奇怪的行为,比如find_element_by_*这类老 API 在某些场景下对 WebElement 的处理和新解释器配合得不太好。
所以我的建议很直接:新装环境,一律选 Python 3.8。这个版本既避开了 Python 3.9+ 对老库的隐性兼容问题,又比 2.7 干净太多——2.7 早已停止维护,新装的系统里很多依赖都拉不下来。如果你手里正好只有 Python 3.11 或更高版本,也不是不能用,但后续安装依赖时你会经常撞见「这个包没有适配 3.11 的 wheel」之类的尴尬,建议直接用pyenv装一个 3.8 作为项目解释器。
python3.8 -m venv /opt/selenium-env source /opt/selenium-env/bin/activate逻辑很简单:第一条命令创建一个独立虚拟环境,路径放在/opt/selenium-env;第二条命令激活它,之后所有 pip 装的包都只属于这个环境,不影响系统全局。用虚拟环境还有一个额外好处——你不需要 root 权限就能装包,也避免了把依赖装乱之后只能重装系统的惨剧。
2.2 pip 安装:锁定 3.141.0 而不是最新版
虚拟环境激活后,第一件事就是安装 Selenium 本身。千万注意版本号写法,这是整个安装过程里最容易踩的坑:
pip install selenium==3.141.0这里用==精确锁定版本,而不是直接pip install selenium。如果你不加版本号,pip 会去拉最新稳定版,装出来的是 4.x。4.x 的 API 和 3.x 差别很大,最典型的是find_element_by_id这类方法在 4.x 里被移除,改用find_element(By.ID, ...)。你拿 3.141.0 时代的代码跑在 4.x 上,光是改这些方法调用就够改一整天的。
还有一点要注意:如果之前已经装过其他版本的 selenium,先卸掉再装比较干净:
pip uninstall selenium -y pip install selenium==3.141.0-y参数跳过卸载确认。这么做是防止旧版本残留文件和新版本互相覆盖,出现那种「明明装的是 3.141.0,跑起来却是另一个版本行为」的玄学问题。装完可以验证一下版本号:
pip show selenium看到Version: 3.141.0就说明装对了。这一步虽然简单,但值得多花十秒钟确认——我见过太多人栽在版本号上,后面所有报错都显得不可理喻。
2.3 固化依赖:requirements.txt 的写法
如果这个环境将来要部署到其他机器上,或者团队成员要复现,最好把依赖写进requirements.txt。Selenium 3.141.0 有一个比较麻烦的点:它依赖urllib3的早期版本协议,如果你在 requirements.txt 里不锁它的传递依赖,新环境可能会拉到一个新版本 urllib3,然后出现InsecureRequestWarning刷屏,虽然不影响功能,但日志会很难看。
我一般会在项目根目录生成一份 requirements.txt,内容如下:
selenium==3.141.0 urllib3==1.26.20生成方式很简单:
pip freeze > requirements.txt但pip freeze会把当前环境所有包全写进去,包括很多无关依赖,可以直接手动写上面那两行,或者 freeze 之后自己挑一下。部署到新环境时一条命令装完:
pip install -r requirements.txt注意urllib3版本不要锁太老,1.26.x 是兼容性最稳的区间,既能被 Selenium 3.141.0 接受,也不会和系统的 requests 冲突。这一点属于血泪经验,当年我图省事没锁 urllib3,新环境装上之后 requests 直接把 urllib3 升到 2.x,Selenium 的底层 HTTP 请求反而不工作了。
3. 浏览器驱动:Selenium 3.141.0 最容易翻车的一环
3.1 ChromeDriver:大版本必须和 Chrome 完全一致
Selenium 本身只是一个操作浏览器的协议库,真正去启动浏览器、执行点击输入动作的,是浏览器驱动。对 Chrome 来说就是 ChromeDriver。Selenium 3.141.0 时代没有后来 4.x 那种自动下载驱动的机制,你必须手动把 ChromeDriver 下载好、放到能被找到的位置。这也是整个环境搭建里翻车率最高的一步。
ChromeDriver 的版本匹配规则极其严格:它和 Chrome 浏览器的主版本号必须一致。比如你的 Chrome 是 120.x,那 ChromeDriver 也必须是 120.x,差一个主版本都不行。下载的时候不要去拿最新的,而要看你本机 Chrome 的实际版本号。
google-chrome --version在 Windows 上,打开 Chrome 的「关于」页面看到版本号,或者命令行里运行:
reg query "HKEY_CURRENT_USER\Software\Google\Chrome\BLBeacon" /v version拿到本机 Chrome 版本后,去 ChromeDriver 的官方下载页面找到对应主版本的压缩包。下载完成后解压,里面是一个可执行文件chromedriver(Windows 下是chromedriver.exe)。
Selenium 3.141.0 对这个文件的核心要求就一句话:它必须能被 Python 进程直接找到,或者你在代码里明确告诉它驱动文件在哪。具体怎么做,下一节说。
3.2 驱动放哪:三种配置方式对比
ChromeDriver 的位置是 3.141.0 配置里最讲究的部分。我常用的方式有三种,按个人偏好排序:
第一种,把 chromedriver 放到系统 PATH 目录下:
sudo mv chromedriver /usr/local/bin/ chmod +x /usr/local/bin/chromedriverLinux 和 macOS 都适用,/usr/local/bin默认就在 PATH 里。chmod +x这句千万别省,Windows 用户复制过来的文件经常不带执行权限,驱动放到 PATH 里却提示找不到,其实是没有可执行权限。
第二种,Windows 下放到 Python 安装目录的 Scripts 文件夹里,比如:
C:\Python38\Scripts\chromedriver.exe这个目录在安装 Python 时通常会被加入系统 PATH,放进去之后同样能被直接识别。
第三种,不在环境变量里放任何东西,而是在代码里显式指定:
from selenium import webdriver driver = webdriver.Chrome(executable_path="/opt/selenium-env/drivers/chromedriver")这种方式适合开发调试阶段,或者你不想污染系统 PATH。但要注意:executable_path参数在 Selenium 4.x 里已经被移除了,替换成了service=参数。所以你如果看到有人用 4.x 的写法去驱动 3.141.0,一定会报TypeError: __init__() got an unexpected keyword argument 'executable_path'。
我实际项目里的习惯是:开发期用第三种,代码里写死驱动路径;部署到线上后统一改成第一种,把驱动放到/usr/local/bin/下。这样测试环境和生产环境的行为不会因为路径差异而打架。
3.3 Firefox 备选:geckodriver 的分发与配置
如果不能装 Chrome,或者要跑的脚本本来就是给 Firefox 写的,那对应的驱动是 geckodriver,配置逻辑和 ChromeDriver 几乎一样,但有一个容易被忽略的坑:geckodriver 的版本与 Firefox 的主版本匹配要求没有 ChromeDriver 那么死,兼容范围宽一些,老版本 geckodriver 也能驱动新版本 Firefox,反过来就不行。
sudo mv geckodriver /usr/local/bin/然后代码里这样用:
from selenium import webdriver driver = webdriver.Firefox(executable_path="/usr/local/bin/geckodriver")另外,Firefox 如果启用了多进程模式,Selenium 3.141.0 在某些场景下会报Expected browser binary location, but unable to find binary in default location,这是因为它找不到 Firefox 可执行文件的默认路径。解决方式是在代码里通过options.binary_location指定:
from selenium import webdriver options = webdriver.FirefoxOptions() options.binary_location = "/usr/lib/firefox/firefox" driver = webdriver.Firefox(firefox_options=options, executable_path="/usr/local/bin/geckodriver")binary_location和executable_path的区别要分清:前者告诉 Selenium 浏览器本体在哪个路径,后者告诉它驱动在哪。很多人两者混为一谈,出了问题时不知道到底是谁找不到谁。这里有个快速判断的方法——报错信息里出现了binary这个词,基本就是浏览器路径的问题;出现executable needs to be in PATH,那一定是驱动路径的问题。
4. 排查避坑:Selenium 3.141.0 高频报错的四个真实场景
4.1 现象一:WebDriverException: 'chromedriver' executable needs to be in PATH
这是国内开发者最多遇到的第一个报错。明明安装了 Selenium,也下载了 ChromeDriver,运行时却提示找不到可执行文件。
原因基本就三个:第一,驱动解压后放在某个普通目录,没做 PATH 配置;第二,Linux 下文件没有可执行权限;第三,文件名不对,比如下载的压缩包里还有个版本号后缀,实际可执行文件名不是chromedriver而是chromedriver_linux64之类。
解决方式按顺序排查:先确认chromedriver文件确实存在,用which chromedriver看系统能不能找到;找不到就把驱动放到/usr/local/bin并加执行权限;文件粘贴过来后先ls -l看一眼权限位。还有一种隐蔽场景:你机器上装过多个 Python 环境,当前激活的虚拟环境 PATH 和你以为的 PATH 不是同一套,这时在代码里直接用executable_path显式指定的方式最保险。
4.2 现象二:SessionNotCreatedException: This version of ChromeDriver only supports Chrome version XX
报错信息很直白:你下载的 ChromeDriver 和你本机的 Chrome 版本对不上。这个错在大版本跨越时尤其明显,比如 Chrome 突然自动更新到 131,而你手里是给 120 用的驱动。
原因就是版本号不匹配。Selenium 3.141.0 本身没有帮你检查驱动和浏览器版本是否一致的能力,全靠自觉。解决方式:打开 Chrome 看当前版本号,去下载对应的 ChromeDriver。但这里有个额外坑——Chrome 若已更新到很新的版本,旧版 ChromeDriver 文件在官方发布页可能已被清理,需要去历史版本列表里翻。此时更省事的办法是临时切换到 Firefox + geckodriver,两者的版本兼容范围宽得多,不耽误手头的工作。
4.3 现象三:unknown error: cannot find Chrome binary
这个报错意味着 ChromeDriver 已经找到了,但它去找 Chrome 浏览器本体时扑了个空。比上一个报错更迷惑,因为它出现在驱动配置看起来很完美的情况下。
原因通常是 Chrome 安装路径不是默认位置。比如公司机器上 Chrome 被放到了自定义目录,或者用的是 Chrome for Testing 这类非标准安装。解决方式相对直接,在代码里用binary_location把浏览器路径指给它:
from selenium import webdriver options = webdriver.ChromeOptions() options.binary_location = "/opt/google/chrome/chrome" driver = webdriver.Chrome(executable_path="/usr/local/bin/chromedriver", options=options)注意参数顺序:3.141.0 的webdriver.Chrome()可以同时接受executable_path和options,但如果你把options写成了位置参数放在最前面,Python 会直接报语法层面的错。这种错其实不算环境问题,属于 API 使用问题,但因为它经常和「找不到驱动」「找不到浏览器」同时出现,我把它也归进环境排错里。
4.4 现象四:ModuleNotFoundError: No module named 'selenium',但明明装过
这条报错会让很多人怀疑人生,因为pip show selenium确实显示已安装,可脚本依然报模块不存在。
原因九成是解释器路径不对。你可能在系统级 Python 里装了 selenium,但跑脚本用的是虚拟环境的 Python;或者反向操作——启动终端时自动激活了某个环境,里面压根没装。还有一种更隐蔽的情况:你的脚本文件名叫selenium.py,放在当前目录下,Python 的 import 机制会优先读取当前目录的同名文件,结果把自己当成这个模块来导入,自然找不到真正的 selenium。
解决方式第一步,打印当前解释器路径和包路径:
which python python -c "import selenium; print(selenium.__file__)"如果which python指向的路径和安装 selenium 的路径不一致,重新激活正确的虚拟环境。第二步,确认没有任何文件和 selenium 模块重名。从那以后,我再也没给脚本起过selenium.py、webdriver.py这类名字,新项目统一放在src/目录下,模块名用项目代号代替。这不是玄学,是 import 机制在教你做人。
4.5 现象五:Message: unknown error: net::ERR_CONNECTION_RESET偶发出现
跑爬虫脚本或自动化测试时,偶尔会有几次请求直接连接重置,重跑一遍又好了。这个问题在 3.141.0 环境下出现频率不低,通常和 Selenium 无关,而是 ChromeDriver 启动的浏览器会话在网络层面被限制。
出现这个现象时,先别急着怀疑环境,观察一下是不是每次都是同一个请求失败。如果只是偶发,大概率是目标站点对自动化访问做了频控,或者是系统代理设置了自动切换导致会话不稳定。可以在启动参数里关掉 Chrome 的代理自动检测、避免走系统代理:
from selenium import webdriver options = webdriver.ChromeOptions() options.add_argument("--no-proxy-server") driver = webdriver.Chrome(executable_path="/usr/local/bin/chromedriver", options=options)用--no-proxy-server明确不走代理,很多网络层玄学问题反倒能压下去。如果是 Docker 容器里跑 3.141.0,还要额外加上--no-sandbox和--disable-dev-shm-usage,否则很容易出现浏览器直接闪退或崩溃,这两个参数我在容器环境里几乎是默认加上去的。
5. 装完怎么验证:跑通一个最小脚本再上项目
环境装好、驱动配好之后,最关键的一步是用一个最小脚本验证整条链路。我每次新配好环境,都会先跑一遍下面这个脚本再做任何事情:
from selenium import webdriver from selenium.webdriver.chrome.options import Options options = Options() options.add_argument("--window-size=1280,800") options.add_argument("--disable-gpu") driver = webdriver.Chrome(executable_path="/usr/local/bin/chromedriver", options=options) driver.get("https://example.com") print("页面标题:", driver.title) driver.quit()这个脚本做的事情很简单:启动 Chrome,打开一个稳定页面,读取标题打印出来,然后关闭浏览器。--window-size=1280,800是让浏览器窗口固定尺寸,避免无头环境下默认大小异常;--disable-gpu是关闭 GPU 加速,减少虚拟机和容器环境里的渲染问题。
预期结果是在终端看到类似页面标题: Example Domain的字样,同时浏览器窗口弹出又自动关闭。如果这一步全通过,说明 Python 环境、Selenium 3.141.0、ChromeDriver、Chrome 浏览器这四层全部打通了。
如果不想弹真实窗口,只想快速验证环境,可以在options里加--headless参数,无头模式下不显示界面,适合放在 CI 流程里做冒烟测试。无头模式和有头模式在绝大多数场景下行为一致,但遇到需要跑 WebGL 或复杂渲染的页面时会有些细微差别,开发期还是建议用有头模式看一眼真实表现。
最后再提醒一个习惯:每次换机器、升 Chrome、重建环境之后,都强制自己跑一遍这个最小脚本,不要直接拿大项目去试。大项目出错时,系统报错往往裹着层层业务代码,很难分清是环境问题还是逻辑问题。而这种几行的小脚本,过了就是环境没问题,不过就是环境配置有问题,排查成本低得多。
Selenium 3.141.0 这套环境,说难也难,说简单也简单。难在版本对齐和驱动路径这些看不见的细节,简单在只要把 Python 版本、Selenium 版本、浏览器驱动版本这三件事理顺,剩下的就是写代码的事。希望这篇记录能帮你省掉几个下午的排查时间,少走我当年走过的弯路。
本文还有配套的精品资源,点击获取