
简介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 甚至更新的版本但很多公司的老系统、爬虫脚本、自动化测试框架里躺着的那份依赖清单写的却是selenium3.141.0。这个版本是 Selenium 3.x 系列最后的稳定版之后整个项目跳到 4.xAPI、驱动管理方式、定位策略全部换了一套。我见过不少开发者把环境从零搭起来一条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.103.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 selenium3.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 selenium3.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内容如下selenium3.141.0 urllib31.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.xSelenium 的底层 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 的官方下载页面找到对应主版本的压缩包。下载完成后解压里面是一个可执行文件chromedriverWindows 下是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_optionsoptions, 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, optionsoptions)注意参数顺序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, optionsoptions)用--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-size1280,800) options.add_argument(--disable-gpu) driver webdriver.Chrome(executable_path/usr/local/bin/chromedriver, optionsoptions) driver.get(https://example.com) print(页面标题:, driver.title) driver.quit()这个脚本做的事情很简单启动 Chrome打开一个稳定页面读取标题打印出来然后关闭浏览器。--window-size1280,800是让浏览器窗口固定尺寸避免无头环境下默认大小异常--disable-gpu是关闭 GPU 加速减少虚拟机和容器环境里的渲染问题。预期结果是在终端看到类似页面标题: Example Domain的字样同时浏览器窗口弹出又自动关闭。如果这一步全通过说明 Python 环境、Selenium 3.141.0、ChromeDriver、Chrome 浏览器这四层全部打通了。如果不想弹真实窗口只想快速验证环境可以在options里加--headless参数无头模式下不显示界面适合放在 CI 流程里做冒烟测试。无头模式和有头模式在绝大多数场景下行为一致但遇到需要跑 WebGL 或复杂渲染的页面时会有些细微差别开发期还是建议用有头模式看一眼真实表现。最后再提醒一个习惯每次换机器、升 Chrome、重建环境之后都强制自己跑一遍这个最小脚本不要直接拿大项目去试。大项目出错时系统报错往往裹着层层业务代码很难分清是环境问题还是逻辑问题。而这种几行的小脚本过了就是环境没问题不过就是环境配置有问题排查成本低得多。Selenium 3.141.0 这套环境说难也难说简单也简单。难在版本对齐和驱动路径这些看不见的细节简单在只要把 Python 版本、Selenium 版本、浏览器驱动版本这三件事理顺剩下的就是写代码的事。希望这篇记录能帮你省掉几个下午的排查时间少走我当年走过的弯路。本文还有配套的精品资源点击获取