三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

避坑指南:从Win11开发到Win7部署,我的Playwright离线迁移血泪史

避坑指南:从Win11开发到Win7部署,我的Playwright离线迁移血泪史

避坑指南:从Win11开发到Win7部署,我的Playwright离线迁移血泪史

那天下午,当我在客户现场的内网Win7电脑上看到ImportError: DLL load failed的红色报错时,后背瞬间渗出一层冷汗——开发环境跑得飞快的自动化脚本,在客户机器上连最基本的导入都失败了。这就是我轻敌的代价:以为用Python打包就能轻松搞定跨系统部署,却不知从Win11到Win7的鸿沟里藏着这么多"暗礁"。

1. 环境差异:那些容易被忽视的"版本陷阱"

第一个耳光来自Python解释器本身。当我习惯性地在客户机器安装Python 3.10时,安装程序直接报错——后来才知道Win7最高只支持到Python 3.8.10。更讽刺的是,这个限制不是写在Python官网的显眼位置,而是藏在 PEP 11 的废弃说明里。

Playwright的版本兼容性更是暗藏杀机。开发时没指定版本安装的1.35版,到了客户环境才发现Win7最高只支持1.15.3。这两个版本的主要API差异包括:

功能点1.35版1.15.3版
选择器语法>>链式操作符仅支持基础CSS/XPath
设备模拟deviceScaleFactor参数需通过viewport手动设置
截图选项支持animations:disabled无此选项

关键教训:永远用pip install package==x.y.z明确版本,特别是在需要支持旧系统时。我现在会在项目README最上方用红色标注:

# 强制环境约束 Python ==3.8.10 playwright ==1.15.3

2. 系统依赖:看不见的"基础设施"

当脚本终于能导入却报api-ms-win-crt-runtime-l1-1-0.dll缺失时,我才意识到问题比想象中复杂。Win7缺少的运行时组件就像隐藏的地雷:

  1. VC++运行库:必须安装vc_redist.x64.exe2015-2019版本
  2. 系统补丁:KB2533623(解决AddDllDirectoryAPI缺失)
  3. 字体配置:部分网页需要额外安装微软雅黑字体

最坑的是这些依赖的报错信息往往具有欺骗性。比如当看到Could not find browser binary时,实际可能是系统缺少d3dcompiler_47.dll——这个文件需要单独从Win10系统复制到Win7的C:\Windows\System32下。

我的解决方案是创建一个precheck.ps1PowerShell脚本来自动检测:

# 检查系统补丁 $hotfix = Get-HotFix | Where-Object {$_.HotFixID -eq "KB2533623"} if (!$hotfix) { Write-Warning "缺少关键系统补丁KB2533623" } # 检查VC++运行库 $vcRegPath = "HKLM:\SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64" if (!(Test-Path $vcRegPath)) { Write-Warning "未检测到VC++ 2015-2019运行库" } # 检查DirectX版本 $dxdiag = [System.Diagnostics.Process]::Start("dxdiag", "/t dxdiag.txt") Start-Sleep -Seconds 3 $dxVersion = Select-String -Path "dxdiag.txt" -Pattern "DDI Version:" if ($dxVersion -notmatch "11") { Write-Warning "DirectX版本低于11" }

3. 离线部署:浏览器二进制文件的"走私"方案

Playwright最特殊之处在于它需要下载特定版本的浏览器内核。在内网环境下,常规的playwright install根本行不通。经过多次尝试,我总结出以下可靠步骤:

完整文件迁移方案

  1. 在联网机器执行安装后,完整打包以下目录:
    • C:\Users\<user>\AppData\Local\ms-playwright(浏览器二进制)
    • C:\Users\<user>\AppData\Local\Programs\Python\Python38\Lib\site-packages\playwright(Python驱动)
  2. 在内网机器创建相同路径,解压文件
  3. 设置环境变量避免自动更新检查:
    set PLAYWRIGHT_DISABLE_UPDATE_CHECK=1

对于需要更高安全性的场景,可以改用Docker构建离线镜像:

FROM python:3.8-slim # 预下载浏览器二进制 RUN pip install playwright==1.15.3 && \ playwright install && \ mkdir /offline-bundle && \ cp -r /root/.cache/ms-playwright /offline-bundle/ # 构建时带上--build-arg BASE_URL=file:///path/to/offline-bundle

4. 测试策略:用虚拟机搭建"犯罪现场"

最深刻的教训来自一个只在客户环境出现的诡异报错——Target closed。后来发现是因为客户机器的IE默认设置拦截了弹窗。这促使我建立了严格的环境沙盒流程:

  1. 镜像准备

    • 使用微软官方Win7 SP1镜像( 下载链接 )
    • 禁用Windows Update防止自动升级
    • 安装基础补丁包:
      wusa.exe KB2533623-x64.msu /quiet /norestart
  2. 差异检测清单

    • 系统编码设置(chcp命令输出)
    • 屏幕DPI缩放比例
    • 默认浏览器及其安全设置
    • 网络代理配置
  3. 自动化验证脚本

import playwright.sync_api def test_basic_operations(): with playwright.sync_api.sync_playwright() as p: # 测试三大浏览器基础功能 for browser_type in [p.chromium, p.firefox, p.webkit]: browser = browser_type.launch() page = browser.new_page() page.goto("about:blank") assert page.title() == "", f"{browser_type.name} title check failed" browser.close() # 检查系统依赖 def check_system_deps(): import ctypes assert ctypes.windll.user32.GetDpiForSystem() == 96, "DPI缩放非100%"

5. 终极解决方案:自建离线仓库

经历多次翻车后,我最终搭建了一个完整的离线部署体系:

文件目录结构

offline_deploy/ ├── python-3.8.10-embed-amd64.zip ├── vc_redist.x64.exe ├── KB2533623-x64.msu ├── packages/ # pip离线包 │ ├── playwright-1.15.3-py3-none-any.whl │ └── ... └── browsers/ ├── chromium-XXXX/ ├── firefox-XXXX/ └── webkit-XXXX/

一键部署脚本(deploy.bat):

@echo off :: 安装系统补丁 wusa.exe KB2533623-x64.msu /quiet /norestart :: 安装VC++运行库 start /wait vc_redist.x64.exe /install /quiet /norestart :: 解压Python tar -xf python-3.8.10-embed-amd64.zip -C C:\Python38 :: 安装pip包 C:\Python38\python.exe -m pip install --no-index --find-links=packages -r requirements.txt :: 部署浏览器 xcopy /E /I browsers "%LOCALAPPDATA%\ms-playwright"

现在每次有新客户需要离线部署时,我都会先问三个问题:

  1. 目标系统是Win7 SP1还是更早版本?
  2. 内网是否有特殊的组策略限制?
  3. 是否需要支持高DPI显示设备?

这三个问题背后,都是我用通宵调试换来的血泪经验。技术债迟早要还,区别只在于是开发时主动还,还是上线后被迫用加班来还。

← 返回列表