
1. 项目概述与需求场景做自动化测试或者爬虫的朋友肯定都遇到过这样的场景公司内网隔离、客户现场不允许外联、云上机器没有公网访问权限结果项目里唯一依赖的Playwright装不上直接卡死在“Downloading browsers”这一步。Playwright这套自动化框架核心能力是把Chromium、Firefox、WebKit三个浏览器的控制逻辑封装成统一API配合Python或JavaScript调用能稳定地操作页面、拦截请求、生成测试报告解决的核心问题就是在受控环境里完成浏览器自动化任务。但它的安装一直让人又爱又恨——npm或pip安装本体只是一小部分真正大头是浏览器二进制文件而这部分默认走的是公共CDN没有外网就寸步难行。说实话我刚开始搞内网自动化环境时也被坑过几次后来摸出一套离线下载和离线安装的完整套路今天就把这套经验整理出来。1.1 核心需求解析离线安装Playwright你要明白它其实分两层第一层是语言库本身也就是Python的playwright包或Node的playwright、playwright-core包第二层是浏览器驱动文件也就是Chromium、Firefox、WebKit的二进制可执行文件。很多人在内网执行pip install playwright成功了但一运行playwright install就报错原因就是浏览器文件没到位。另外Playwright的组织方式也决定了离线操作必须分步处理——它不像普通pip包那样把全部内容塞进一个wheel里而是运行时按需下载浏览器。这个设计平时方便离线时就特别磨人理解了这一点你就能明白后面每一招都是冲着解决哪层问题去的。1.2 适用人群与典型场景这篇内容主要面向三类人一是企业内部做测试平台开发、需要在隔离网络部署测试环境的工程师二是做爬虫采集、需要把自动化任务部署到客户内网服务器的脚本作者三是在学习Playwright但恰好网络不稳定、下载浏览器经常失败的入门玩家。典型场景包括用离线包搭一套Windows服务器上的自动化测试环境、把Playwright塞进Docker镜像后再传到私有仓库、给没有外网的测试机批量安装相同版本。不管你是Python系还是Node系这套离线流程都通用区别只在下载命令的不同写法。2. 离线安装包的获取策略离线下载这事核心思路就一条在一台有网机器上把“语言库”和“浏览器文件”都准备好然后搬到内网安装。听起来简单但实际操作有几个容易忽略的坑比如上游依赖包的遗漏、浏览器文件与语言库版本不匹配、以及平台架构不一样导致白下载。我先分别拆解两条路径再给一套可复用的组合方案。2.1 语言库离线包下载方法Python环境建议使用pip download这个方法会把指定包及其所有依赖全部下载到本地目录非常干净。举例pip download playwright1.40.0 -d ./playwright_packages -r requirements.txt这里需要先准备一个requirements.txt列出你项目里用到的所有依赖。pip download有个好习惯它只下载不安装而且默认会把依赖包一起拉下来但注意它不会自动下载Playwright所需的浏览器文件。当然如果你只想给当前这台机器做缓存也可以直接pip wheel playwright -w ./wheelhouse。Node环境则用npm pack playwright之类的命令或直接npm install playwright后再把node_modules整个打包多数人倾向后者省事但包体积会膨胀不少。我个人更喜欢的做法是在有网机器上先建一个临时项目npm install playwright指定版本 --save再把package.json、package-lock.json和node_modules一起打包这样版本信息锁死不容易出错。2.2 浏览器二进制文件的离线获取这是离线安装最容易卡壳的地方。Playwright的浏览器文件默认安装到用户目录的缓存文件夹Windows下一般是C:\Users\用户名\AppData\Local\ms-playwrightLinux下是~/.cache/ms-playwrightMac下是~/Library/Caches/ms-playwright。你只需要在有网机器上执行一次完整的浏览器安装然后把整个ms-playwright文件夹压缩带走。命令如下playwright install chromium playwright install firefox playwright install webkit注意别只带一个浏览器要看你的测试代码实际引用哪个如果做了跨浏览器兼容测试三个都得装。另外如果你用的是Playwright 1.40以上版本浏览器版本号和包版本是严格绑定的下载前必须确认playwright包的版本和浏览器缓存内容一致最可靠的方法就是在有网机器上用同一份requirements.txt或package.json安装后再打包。打包命令建议用tar或7z避免压缩格式在跨平台传输时丢失符号链接Windows到Linux尤其要留意比如Chromium的chrome_crashpad_handler等文件权限很容易丢到时候内网装上一堆权限错误看着头大。2.3 生态扩展midscene等被Playwright调用的原理顺便说一下最近热起来的midscene这类工具它也是通过Playwright驱动浏览器做页面理解和操作核心原理是Playwright向外提供了一套CDP协议的封装以及浏览器实例的启动与通信能力midscene这类上层框架只要拿到Playwright的Browser对象就可以在页面上下文中注入自己的脚本和数据采集逻辑。对离线部署来说这意味着你不仅要把Playwright本体装好还要确认你的上层框架是否带了自己的依赖比如midscene依赖的模型服务、额外Node包等。这个在离线同步时容易被漏掉建议把整个项目的依赖列表都拉出来统一处理而不是只关心Playwright那一层。3. 离线安装实操全流程理论讲完直接上一套我从头到尾实操过的流程。这里以Windows内网服务器为例用Python版本演示Node版本会在旁边标注差别。整套流程分四步每一步我都标注了容易翻车的地方你可以直接照抄。3.1 在有网环境中准备离线资源首先找一台和你的内网目标机器同架构、同系统版本的机器Windows就找WindowsLinux就找Linux这点非常重要。比如你在Mac上下载的浏览器二进制拿到Windows服务器上大概率跑不起来。准备工作分为三个目录libraries/存放pip或npm下载的依赖包browsers/存放Playwright的浏览器缓存目录install_scripts/存放安装脚本。Python侧执行mkdir offline_pw cd offline_pw pip download playwright1.40.0 -d libraries/ playwright install chromium xcopy /E /I %LOCALAPPDATA%\ms-playwright browsers\Node侧执行mkdir offline_pw cd offline_pw npm init -y npm install playwright1.40.0 npx playwright install chromium xcopy /E /I %LOCALAPPDATA%\ms-playwright browsers\这会把Playwright的浏览器缓存整个复制出来。执行完检查一下browsers\目录下应该有三个甚至更多的子目录每个目录名形如chromium-XXXX、ffmpeg-XXXX、headless_shell-XXXX等这些就是真正需要的二进制。特别注意只装Chromium默认也会拉下载ffmpeg和headless_shell别删掉删了之后跑Headless模式会报错。3.2 内网部署与安装命令将整个offline_pw目录拷贝到内网机器比如放在C:\offline_pw。然后开始安装。Python侧用pip install --no-index --find-links指定本地目录cd C:\offline_pw pip install --no-index --find-linkslibraries playwright1.40.0执行过程中如果提示缺依赖多半是你用pip download时落下了某个传递依赖回头在libraries里找找有没有对应的whl文件没有就回到有网机器补一下。Node侧就更直接把node_modules整个拷到项目目录就行如果当时用了npm install建议把node_modules和package-lock.json一起复制然后在内网npm ci --offlinenpm ci依赖缓存如果缓存里没有包会失败稳妥点还是直接拷贝node_modules。装完语言库接下来手动放置浏览器缓存目录。Windows下先确认当前用户目录echo %LOCALAPPDATA%把browsers下的内容复制到%LOCALAPPDATA%\ms-playwright。Linux下则放到~/.cache/ms-playwright。复制完可以用一种很傻但有效的方法验证逐个运行sleep、运行程序看是否报缺少浏览器或者直接用官方提供的playwright install --dry-run查看待安装列表是否已经满足。3.3 配置环境变量与依赖检查这一步很多人忽略导致离线安装后浏览器启动报错。首先Playwright允许通过环境变量PLAYWRIGHT_BROWSERS_PATH自定义浏览器存放位置如果你不想把包解压到用户目录可以设置成项目内路径set PLAYWRIGHT_BROWSERS_PATHC:\offline_pw\browsers这个变量最好在启动测试脚本前设置这样多个项目可以共用一个浏览器缓存也可以避免C盘空间不足。另一个环境变量是PLAYWRIGHT_DOWNLOAD_CONNECTION_TIMEOUT在线安装时可能用得上离线不需要。接下来写一个快速验证脚本确认语言库和浏览器能配合工作from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch() page browser.new_page() page.goto(file:///C:/offline_pw/test.html) print(page.title()) browser.close()如果走到browser p.chromium.launch()报错先别急下面一个问题一个问题的排查。4. 常见问题排查与避坑指南离线安装这事儿坑基本都在三个方面下载过程不完整、版本不匹配、系统运行库缺失。我把这些年实际踩过的问题整理成一份排查清单按频率从高到低排你遇到哪个直接对号入座。4.1 npx playwright install失败原因分析新手最常见的报错是npx playwright install在终端里一直卡着转圈然后超时。其实这不是真正的网络问题而是版本源配置导致。npx playwright install本质是下载浏览器二进制它默认从CDN拉取如果内网访问不了就会失败。解决办法是设置镜像环境变量set PLAYWRIGHT_DOWNLOAD_HOSThttps://npmmirror.com/mirrors/playwright/但这本身还是要联网所以离线场景下不能依赖这个方法。另一种情况是报Failed to install browsers但明明你已经拷贝了ms-playwright目录这往往是缓存目录结构不对——ms-playwright文件夹里面必须直接是chromium-1110这样的版本号目录如果你多套了一层目录比如browsers\ms-playwright\chromium-1110Playwright是识别不到的。另外npx playwright install还有一个隐藏依赖它会在安装时检查~/AppData/Local/ms-playwright下是否存在被当前包版本使用的浏览器文件夹名如果版本号不匹配它甚至无视你的已有文件直接重新下载所以版本一致性是首要问题。4.2 浏览器启动失败与系统依赖缺失这个坑在Linux内网环境尤其致命因为Playwright的Chromium需要一系列系统动态库。即使你把所有二进制都放到位一运行还是报错典型错误是error while loading shared libraries: libnss3.so。解决办法是提前在离线服务器上装齐所有系统包不同发行版包名不同但常见的几个都逃不掉依赖库常见包名Ubuntu/Debian大致用途libnss3libnss3网络安全服务Chromium核心依赖libatk1.0libatk1.0-0无障碍组件库libatk-bridgelibatk-bridge2.0-0无障碍桥接libcups2libcups2打印服务libxkbcommonlibxkbcommon0键盘事件处理libgbm1libgbm1图形内存管理libpangolibpango-1.0-0文本渲染如果内网机器本身没有这些包可以先在有网机器上apt download相关deb包再传上去安装或者直接要求运维把常用基础库装好。这里有个经验之谈宁可把依赖装多也别装少因为缺一个库就得重新跑一遍流程来回折腾的时间够做好几个用例了。4.3 版本一致性管理技巧我在最初做离线包时吃过一次大亏。当时从一台机器上下载了Playwright 1.38的浏览器缓存结果内网装的是1.40的pip包运行直接报“Executable doesnt exist”排查半天才发现是两个版本号对应的chromium目录名不同。这里的关键在于浏览器缓存目录的命名后缀是随Playwright版本变动的比如chromium-1067对应某个特定版本范围不能跨版本使用。我的建议是在离线准备目录里放一个版本信息文件把Playwright版本号和对应的浏览器文件夹名记录下来例如echo playwright1.40.0 version_info.txt echo chromium-1112 version_info.txt echo firefox-1350 version_info.txt内网安装时先对照版本再复制目录。这个看起来不起眼的小动作能帮你节省大量排查时间。4.4 离线容器镜像制作注意事项如果你是用Docker部署方法类似但更精细。Dockerfile里分两步先在一个光秃秃的运行环境里COPYms-playwright然后设置ENV PLAYWRIGHT_BROWSERS_PATH/ms-playwright最后再安装Python或Node依赖。这里要注意不要试图把浏览器目录放到/root/.cache因为容器用户可能不是root会导致权限问题。更稳的方式是统一指定一个固定路径并确保运行用户有读权限。我自己常用的是FROM python:3.11-slim WORKDIR /app COPY browsers/ /ms-playwright/ ENV PLAYWRIGHT_BROWSERS_PATH/ms-playwright COPY libraries/ /libraries/ RUN pip install --no-index --find-links/libraries playwright1.40.0 COPY tests/ /app/tests/ CMD [python, -m, pytest]构建时用docker build --network host确保有网阶段正常在内网构建就直接利用本地镜像不再需要外部网络。这个方法我在多个项目里用过稳定度很高。5. 常见问题速查与经验总结最后这张速查表是我把上面所有经验浓缩出来的平时给团队分享或者自己备忘都方便。现象直接原因处理建议pip install playwright成功但启动报错浏览器二进制缺失手动复制浏览器缓存到%LOCALAPPDATA%\ms-playwright浏览器报Executable doesnt exist版本目录不匹配检查package.json或requirements.txt锁定版本并重新打包Linux运行缺库系统库缺失安装libnss3、libatk等依赖包Windows运行提示DLL load failed缺少VC运行库安装Microsoft Visual C Redistributablenpx playwright install无限卡住下载源不可达离线环境不要依赖该命令用本地缓存目录复制浏览器后仍提示无法找到目录层级错误确认chromium-XXXX目录直接位于ms-playwright下Docker容器内无权限缓存目录在root路径设置PLAYWRIGHT_BROWSERS_PATH并赋权根据我个人的实际操作体会离线安装Playwright这件事最重要的其实不是某个具体命令而是提前花十分钟把目标环境梳理清楚操作系统、架构、Python或Node版本、Playwright版本、需要的浏览器类型全都确定下来再准备离线包能省下后面三小时的折腾。还有一个小技巧值得分享给所有人把有网环境里整个ms-playwright目录压缩后附带一个sha256sum校验文件一起传内网部署前先校验一下文件完整性因为大文件传到一半被截断的情况太常见了校验这一步能替你挡掉一半以上的诡异问题。希望这份流程能帮你在内网环境里彻底摆脱Playwright安装的噩梦顺利跑起自动化测试。