Playwright网页自动化实战:从安装、定位到批量任务
先交代一个背景Selenium 这套 Web 自动化方案在测试和爬虫领域用的时间很长但它的痛点也很真实——浏览器驱动要和浏览器版本严格对应下载驱动经常卡住写脚本还要处理各种显式等待。这次我们来看 Playwright一个由微软开源维护的 WEB 自动化框架。它把驱动管理、启动浏览器、录制脚本、断言等待这些事全部打包了新的自动化项目用它可以省掉大量基础设施工作。这篇文章只讲干货Playwright 是什么、怎么安装、怎么启动、怎么用 codegen 录制脚本、怎么处理 iframe 和定位元素、怎么做接口调用和批量任务、遇到问题怎么排查。不管你是测试工程师、爬虫开发还是做 RPA 流程只要涉及网页自动化这篇文章可以直接收藏。先说清楚一个态度Selenium 不需要被“踩死”老项目继续维护完全没问题但如果你现在要开新项目我更建议先试 Playwright。下面从核心能力开始。1. Playwright 核心能力速览能力项说明项目类型开源 Web 自动化测试框架维护方Microsoft微软支持浏览器Chromium、Firefox、WebKit支持语言Python、JavaScript / TypeScript、Java、.NET驱动管理内置浏览器驱动自动匹配版本无需手动下载 chromedriver脚本录制playwright codegen一键录制生成脚本元素定位支持 role、text、css、xpath、get_by_ 系列定位器自动等待内置 auto-wait大部分场景不需要手写 sleep运行模式支持无头 headless 和有头 headed 模式并发与批量支持多 context、多 worker 并行执行接口能力提供 Page / Frame / BrowserContext 三层 API内置 APIRequestContext适用平台Windows、Linux、macOS场景定位WEB 自动化测试、网页数据采集需授权、RPA 流程自动化从这张表能看出Playwright 和 Selenium 最大的差异不在“能不能点按钮”而在工程化能力驱动不用管、等待不用写、录制开箱即用。下面逐步展开。2. 适用场景与使用边界2.1 适合谁用Playwright 最典型的四类用户Web 自动化测试工程师需要做 UI 回归、多浏览器兼容、登录流程、支付流程、表单校验等测试用例。爬虫开发需要处理动态渲染页面、点击翻页、滚动加载、iframe 内嵌内容、文件下载。RPA 流程开发者需要把重复的网页操作固化成脚本比如定时提交报表、批量查询、数据搬运。前端开发用 codegen 快速复现 bug 操作路径或者给 CI 加 E2E 测试。2.2 能解决什么问题不需要再为浏览器驱动版本发愁。Selenium 时代“浏览器驱动怎么判断下载哪个版本”是常见问题Playwright 安装时自动拉取匹配版本的浏览器和驱动。不需要大量显式等待。页面加载、元素出现、动画结束这些情况Playwright 会自动等待。一个脚本可以在 Chromium、Firefox、WebKit 三种内核上跑浏览器兼容测试不用维护三套代码。录制功能可以快速生成脚本骨架再手工补充断言和边界处理。2.3 使用边界与合规提醒这部分必须说清楚自动化脚本只能用于自己有权限测试或已获授权的系统。对于需要登录、付费、验证码保护的业务系统请先获得书面授权。本文不讨论绕过验证码、绕过反爬系统、绕过登录风控的方法。像“滑块验证自动过”“瑞数逆向”这类需求如果对应系统不是你自己的属于破坏安全边界不应实施。网站检测到自动化痕迹本身是正常防御行为。如果测试自己的网站时被检测建议走测试环境或与站点运维沟通而不是研究对抗方案。采集公开数据时遵守目标网站的 robots 协议、服务条款和当地法律法规控制请求频率不要影响目标站点稳定性。3. Playwright 环境准备与安装3.1 语言环境Playwright 官方支持 Python、Node.js、Java 和 .NET。以下以 Python 为例这也是目前国内用最多的方式。Python 建议使用 3.8 及以上版本。可以先确认版本python --version pip --version3.2 安装 Playwright 库pip install -U playwright安装完成后检查版本playwright --version3.3 安装浏览器这一步是 Playwright 和 Selenium 体验差异最大的地方。Selenium 需要你手动下载 chromedriver还要匹配浏览器版本Playwright 直接用官方命令下载配套浏览器playwright install chromium如果只需要默认浏览器执行这一条就行。需要 Firefox 和 WebKit 就分别执行playwright install firefox playwright install webkit3.4 Linux 环境补充系统依赖在 Linux 服务器上运行浏览器可能缺系统库建议使用带依赖安装playwright install --with-deps chromium这条命令需要 root 权限会安装浏览器运行所需的系统库。如果没有 root 权限也可以手动安装依赖但比较麻烦更推荐在 Docker 里跑。3.5 验证安装from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch() page browser.new_page() page.goto(https://example.com) print(page.title()) browser.close()能输出Example Domain说明环境已经通。这段代码跑的是无头模式不弹窗适合服务器上验证。4. Playwright 启动方式与浏览器管理4.1 同步 API 入门Playwright 提供sync_playwright和async_playwright两套 API。普通脚本和测试用例用同步 API 就够from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch( headlessFalse, # False 时显示浏览器窗口方便调试 slow_mo500 # 每一步操作延迟 500ms看过程用 ) context browser.new_context( viewport{width: 1280, height: 800}, localezh-CN ) page context.new_page() page.goto(https://example.com) page.screenshot(pathexample.png) browser.close()启动流程是固定的playwright启动浏览器实例 →new_context创建独立上下文 →new_page创建页面。4.2 Browser、Context、Page 三层 API这是理解 Playwright 的关键Browser浏览器进程。一个进程可以创建多个 context。BrowserContext类似一个“隐身窗口”。每个 context 的 cookie、缓存、存储是隔离的。Page页面实例。每个 context 可以有多个 page。批量任务的核心思路就在这里每个任务用独立 context互不污染登录状态和数据。4.3 复用本机已安装的 Chrome如果不希望下载 Chromium可以直接指定使用系统里已有的 Chromebrowser p.chromium.launch(channelchrome)前提是本机装了 Chrome 浏览器。channelmsedge则使用 Edge。4.4 启动放桌面浏览器跑任务用无头开发调试阶段建议headlessFalse能看到操作过程定位问题更快。CI 或批量任务阶段切回headlessTrue性能和稳定性更好。browser p.chromium.launch(headlessTrue, args[--disable-gpu])5. Playwright 功能测试与效果验证5.1 用 codegen 录制脚本Playwright 自带录制工具这是很多人入门最快的路径。playwright codegen https://example.com执行后会打开浏览器窗口和一个代码录制面板。你在浏览器里的点击、输入、跳转操作会实时生成 Python 代码。录制完成后把代码复制出来保存成test_demo.py即可。这套流程的价值在于先让工具生成 80% 的脚本骨架剩下 20% 的断点和异常处理自己补。相比 Selenium 从零手写定位器效率高很多。codegen 生成的代码默认带定位器和操作步骤但通常不建议直接上生产需要手工补充断言和容错。5.2 元素定位方法定位器是 Playwright 的核心。推荐顺序是角色定位 文本定位 属性定位 CSS/XPath。# 角色定位最推荐 page.get_by_role(button, name登录).click() # 文本定位 page.get_by_text(注册).click() # 占位符定位 page.get_by_placeholder(请输入手机号).fill(13800000000) # CSS 定位 page.locator(#submit-btn).click() # XPath兜底方案 page.locator(xpath//button[contains(text(),提交)]).click()判断定位是否成功的标准只有一个元素存在且可操作。建议先用locator.count()确认匹配数量避免定位到多个元素时报 strict mode 错误。5.3 iframe 内元素处理iframe 在登录弹窗、支付组件、第三方地图中很常见。Selenium 需要切换 driver 的 frame 上下文Playwright 用frame_locator直接在 iframe 内定位# 如果 iframe 有 id frame page.frame_locator(#third-party-frame) frame.get_by_role(button, name同意).click() # 也可以先拿 Frame 对象 frame page.frame(frame-name) frame.fill(#search, playwright)处理 iframe 常用排查思路先用page.frames查看页面里有哪些 frame确认 id 或 name再决定用哪种方式。for f in page.frames: print(f.name, f.url)5.4 等待与断言Playwright 的内置 auto-wait 能处理大多数元素等待不需要手动sleep。需要显式等待时page.wait_for_load_state(networkidle) # 网络空闲 page.wait_for_timeout(2000) # 兜底等待不建议滥用测试断言建议用expectfrom playwright.sync_api import expect expect(page).to_have_title(首页) expect(page.locator(.success)).to_be_visible() expect(page.locator(#count)).to_have_text(100)用expect而不是time.sleep的原因在于expect会自动重试直到条件满足或超时既稳定又不会白白浪费固定等待时间。5.5 截图、PDF 与文件下载# 全屏截图 page.screenshot(pathfull.png, full_pageTrue) # 元素截图 page.locator(.card).screenshot(pathcard.png) # 触发下载 with page.expect_download() as download_info: page.get_by_role(link, name下载报表).click() download download_info.value download.save_as(report.xlsx)5.6 多标签页处理点击一个链接后新开标签页很常见。Playwright 不需要 switch_to.window直接用context.expect_pagewith context.expect_page() as new_page_info: page.get_by_role(link, name新窗口打开).click() new_page new_page_info.value new_page.wait_for_load_state() print(new_page.title())5.7 移动端模拟Playwright 内置设备参数可以模拟 iPhone 和 Android 的浏览器环境from playwright.sync_api import sync_playwright, devices with sync_playwright() as p: browser p.chromium.launch() context browser.new_context(**devices[iPhone 13]) page context.new_page() page.goto(https://example.com) print(page.viewport_size)这对移动端 WEB 自动化非常实用不需要真机或模拟器。6. Playwright 接口 API 调用与批量任务6.1 内置 APIRequestContextPlaywright 除了操作浏览器还提供request上下文可以在同一个脚本里发 HTTP 请求用来准备测试数据或校验接口from playwright.sync_api import sync_playwright with sync_playwright() as p: request_context p.request.new_context() resp request_context.get(https://httpbin.org/get) print(resp.status) print(resp.json()) # 带 JSON 的 POST post_resp request_context.post( https://httpbin.org/post, data{name: playwright, role: tester} ) print(post_resp.json()) request_context.dispose()这里的价值在于Playwright 既能驱动真实浏览器又能直接发接口请求可以做到 UI 和接口混合验证不需要在脚本里额外引入 requests 库去维护一套 Cookie。6.2 批量任务设计批量任务最常见的形态是从文本文件或接口拿一批 URL逐个打开页面抓取数据或截图。import json from playwright.sync_api import sync_playwright urls [ https://example.com/page/1, https://example.com/page/2, https://example.com/page/3, ] results [] with sync_playwright() as p: browser p.chromium.launch(headlessTrue) for url in urls: context browser.new_context() page context.new_page() try: page.goto(url, timeout30000) title page.title() results.append({url: url, title: title}) page.screenshot(pathfshot_{urls.index(url)}.png) except Exception as exc: results.append({url: url, error: str(exc)}) finally: context.close() browser.close() with open(results.json, w, encodingutf-8) as f: json.dump(results, f, ensure_asciiFalse, indent2)这个脚本的核心设计是每个 URL 一个独立 context每个任务 try/except 包裹单条失败不影响整体最后统一写结果文件。批量任务必须加日志和单条失败隔离否则一个页面超时整个任务队列就断了。6.3 用 pytest-playwright 做并行测试安装 pytest 插件pip install pytest-playwright写一个测试文件def test_login(page): page.goto(https://example.com/login) page.get_by_placeholder(用户名).fill(demo) page.get_by_placeholder(密码).fill(123456) page.get_by_role(button, name登录).click() expect(page).to_have_url(https://example.com/home)命令行并行执行pytest tests/ -n 4-n是 pytest-xdist 的参数会同时起多个 worker。并行执行时要注意不要共享同一个 context 里的登录态数据每条用例尽量自包含不依赖执行顺序。6.4 定时批量任务批量网页操作可以交给系统定时任务。Linux 用 crontab0 8 * * * cd /opt/playwright-project /usr/bin/python3 run_batch.py logs/batch.log 21Windows 用任务计划程序。定时任务建议设置日志轮转避免日志文件无限增长。7. 资源占用与性能观察7.1 浏览器自动化看哪些资源Playwright 是浏览器自动化不依赖 GPU主要看 CPU 和内存。启动一个 Chromium 无头实例内存占用通常在几百 MB 级别实际值受页面复杂度影响。任务开得越多内存占用线性增长。观察方法Windows任务管理器里看 python 和 chrome 进程的 CPU / 内存。Linuxtop -c或free -h查看整体内存使用。单个脚本内browser.contexts的数量可以帮助判断是否存在上下文泄漏。7.2 影响性能的因素并发 context 数量并发越多内存越高不是无限制增加。页面数量每个 page 都会加载 JS、图片、样式复杂度决定内存。无头与有头有头模式需要渲染完整窗口内存占用更高。截图频率截图会占用临时磁盘空间批量截图要清理输出目录。slow_mo调试参数生产环境务必关掉否则批量任务会慢好几倍。7.3 降低资源占用的方法批量任务统一用headlessTrue。控制并发数量建议先从小并发开始观察内存再逐步调大。每个 context 用完立即context.close()不要长时间保持。用page.route拦截不必要的图片和字体请求能明显降低带宽和渲染消耗。需要长连接请求时合理设置timeout避免线程长期挂起。8. Playwright 常见问题与排查方法问题现象可能原因排查方式解决方案启动浏览器失败target closed浏览器崩溃或页面被提前关闭查看堆栈日志确认browser.close()是否提前执行检查代码执行顺序用 with 块管理生命周期浏览器下载太慢或失败网络到官方 CDN 不稳定查看下载进度和错误码配置国内镜像源或使用离线安装包环境变量设置下载地址元素定位不到元素在 iframe 内、属性动态变化、需要滚动用page.frames查看 iframe用locator.count()确认数量改用 frame_locator 或 get_by_role 等更强定位方式点击被其他元素遮挡有弹窗、遮罩层或元素未完全渲染截图检查当前页面状态先关闭弹窗或调用scroll_into_view_if_needed()页面跳转后操作还在旧页面导航未完成就开始下一步检查是否有 wait_for_load_state在跳转后等待 load 或 networkidle 状态并发任务偶发失败多个 context 共享资源或有隐式依赖查看失败日志的时间点和 URL每个任务使用独立 context任务内自包含接口请求超时目标接口响应慢或网络受限单独用 curl 验证接口可用性调大 timeout增加重试逻辑反自动化检测导致行为异常网站识别到浏览器被自动化控制仅限测试自己系统时排查与站点运维沟通使用测试环境不对第三方系统做对抗绕过codegen 录制的脚本回放失败录制时和回放时页面状态不一致对比两步之间的页面变化补充 expect 断言和显式等待8.1 关于浏览器驱动版本匹配Selenium 用户经常纠结“浏览器驱动怎么判断下载哪个版本”在 Playwright 里这个问题基本消失了。playwright install会自动下载和库版本匹配的浏览器。如果项目里需要指定特定浏览器版本可以在playwright配置文件中设置browserVersion但日常使用默认配置就够。8.2 关于离线安装内网服务器无法直接下载浏览器时分为两步先在能联网的机器上执行playwright install chromium然后将用户缓存目录下的浏览器包拷贝到内网放到相同路径或通过环境变量指定浏览器路径。具体路径因系统而异离线部署时需要实测确认。9. 最佳实践与使用建议9.1 先录制再精调新页面自动化不要一上来手写定位器。先playwright codegen录制一遍看生成的定位器是否稳定再补断言和异常分支。录制骨架可以节省大量时间。9.2 定位器优先级优先使用get_by_role和get_by_label它们更接近用户视角页面布局变化时不容易挂。CSS 定位适合有明显 class/id 的稳定元素。XPath 只在没有更好方案时使用并且尽量短。9.3 第一次先跑小参数不管写什么自动化任务先跑 1 个页面、1 个 context确认流程通了再上批量。批量任务先开 2 个并发观察资源占用后再逐步加大。9.4 目录管理建议目录结构playwright-project/ ├── tests/ # 测试用例 ├── scripts/ # 批量任务脚本 ├── input/ # 输入数据如 URL 列表 ├── output/ # 输出结果截图、JSON、日志 ├── logs/ # 运行日志 └── requirements.txt模型文件、输入素材、输出结果分开管理是工程化底线避免输出文件覆盖输入文件。9.5 加日志和失败重试批量任务必须有日志脚本开始和结束分别记录时间和结果。失败重试建议采用“单条任务重试 2 次仍失败则跳过并记录”的策略不要无限重试。import time def run_with_retry(task, retries2): for attempt in range(retries 1): try: return task() except Exception as exc: if attempt retries: raise time.sleep(2 ** attempt)9.6 接口服务限制访问范围如果给 Playwright 脚本封装了 Web 服务或 API必须限制访问范围不要直接暴露到公网。方案包括绑定 127.0.0.1、增加 token 鉴权、设置请求频率限制。9.7 合规复核涉及登录、个人信息、版权素材、账号操作时发布或商用前确认授权情况。自动化为工作提效没问题但前提是系统属于你或被授权使用。10. 总结与下一步Playwright 最值得尝试的三件事playwright codegen录制脚本、get_by_role定位器、多 context 批量任务。这三个能力分别解决了 Selenium 时代“脚本入门慢、定位容易碎、并发管理麻烦”的问题。最先验证的功能建议是 codegen。随便打开一个测试站点录制一个登录或查询流程回放一遍你就会感受到“不用手动等和不用管驱动”的体验差距。最容易踩的坑集中在三处浏览器下载失败、iframe 内元素定位不到、并发任务资源竞争。遇到问题优先看日志和页面截图不要盲目加 sleep。后续扩展方向接入 pytest 做 E2E 测试把批量任务接到 CI 流水线用 Playwright MCP 让 AI 助手直接操作浏览器做前端 bug 复现如果做网页数据采集先确认目标站点授权和频率控制。Selenium 的老项目可以继续跑但新项目从 Playwright 开始会省掉很多不必要的折腾。