摘要:本文从 Python 开发者视角出发,讲清楚 playwright 这个 Python 模块的本质、它能做什么、和 Selenium 的本质区别,以及为什么它值得你从零认真学。
一、Playwright 不是一个"测试工具"
很多资料一上来就说:
Playwright 是一个自动化测试工具。
这句话对,但不准确。
更准确的说法是:
Playwright 是一个用于控制浏览器的 Python 模块。
你可以这样理解:
import playwright
它的本质能力只有一件事:
用 Python 代码控制浏览器行为
至于"测试"“爬虫”“监控”,只是使用场景,不是模块本身。
二、playwright 模块能做什么?
#mermaid-svg-aFtvRFMQh4yuCyHa{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-aFtvRFMQh4yuCyHa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-aFtvRFMQh4yuCyHa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-aFtvRFMQh4yuCyHa .error-icon{fill:#552222;}#mermaid-svg-aFtvRFMQh4yuCyHa .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-aFtvRFMQh4yuCyHa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-aFtvRFMQh4yuCyHa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-aFtvRFMQh4yuCyHa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-aFtvRFMQh4yuCyHa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-aFtvRFMQh4yuCyHa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-aFtvRFMQh4yuCyHa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-aFtvRFMQh4yuCyHa .marker{fill:#333333;stroke:#333333;}#mermaid-svg-aFtvRFMQh4yuCyHa .marker.cross{stroke:#333333;}#mermaid-svg-aFtvRFMQh4yuCyHa svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-aFtvRFMQh4yuCyHa p{margin:0;}#mermaid-svg-aFtvRFMQh4yuCyHa .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-aFtvRFMQh4yuCyHa .cluster-label text{fill:#333;}#mermaid-svg-aFtvRFMQh4yuCyHa .cluster-label span{color:#333;}#mermaid-svg-aFtvRFMQh4yuCyHa .cluster-label span p{background-color:transparent;}#mermaid-svg-aFtvRFMQh4yuCyHa .label text,#mermaid-svg-aFtvRFMQh4yuCyHa span{fill:#333;color:#333;}#mermaid-svg-aFtvRFMQh4yuCyHa .node rect,#mermaid-svg-aFtvRFMQh4yuCyHa .node circle,#mermaid-svg-aFtvRFMQh4yuCyHa .node ellipse,#mermaid-svg-aFtvRFMQh4yuCyHa .node polygon,#mermaid-svg-aFtvRFMQh4yuCyHa .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-aFtvRFMQh4yuCyHa .rough-node .label text,#mermaid-svg-aFtvRFMQh4yuCyHa .node .label text,#mermaid-svg-aFtvRFMQh4yuCyHa .image-shape .label,#mermaid-svg-aFtvRFMQh4yuCyHa .icon-shape .label{text-anchor:middle;}#mermaid-svg-aFtvRFMQh4yuCyHa .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-aFtvRFMQh4yuCyHa .rough-node .label,#mermaid-svg-aFtvRFMQh4yuCyHa .node .label,#mermaid-svg-aFtvRFMQh4yuCyHa .image-shape .label,#mermaid-svg-aFtvRFMQh4yuCyHa .icon-shape .label{text-align:center;}#mermaid-svg-aFtvRFMQh4yuCyHa .node.clickable{cursor:pointer;}#mermaid-svg-aFtvRFMQh4yuCyHa .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-aFtvRFMQh4yuCyHa .arrowheadPath{fill:#333333;}#mermaid-svg-aFtvRFMQh4yuCyHa .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-aFtvRFMQh4yuCyHa .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-aFtvRFMQh4yuCyHa .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aFtvRFMQh4yuCyHa .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-aFtvRFMQh4yuCyHa .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aFtvRFMQh4yuCyHa .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-aFtvRFMQh4yuCyHa .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-aFtvRFMQh4yuCyHa .cluster text{fill:#333;}#mermaid-svg-aFtvRFMQh4yuCyHa .cluster span{color:#333;}#mermaid-svg-aFtvRFMQh4yuCyHa div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-aFtvRFMQh4yuCyHa .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-aFtvRFMQh4yuCyHa rect.text{fill:none;stroke-width:0;}#mermaid-svg-aFtvRFMQh4yuCyHa .icon-shape,#mermaid-svg-aFtvRFMQh4yuCyHa .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aFtvRFMQh4yuCyHa .icon-shape p,#mermaid-svg-aFtvRFMQh4yuCyHa .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-aFtvRFMQh4yuCyHa .icon-shape .label rect,#mermaid-svg-aFtvRFMQh4yuCyHa .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aFtvRFMQh4yuCyHa .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-aFtvRFMQh4yuCyHa .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-aFtvRFMQh4yuCyHa :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
playwright 模块
启动浏览器
打开页面
操作页面元素
监听网络请求
截图 / 录屏
执行 JavaScript
典型能力清单
| 启动浏览器 | playwright.chromium.launch() |
| 新建页面 | browser.new_page() |
| 元素定位 | page.get_by_role() |
| 元素操作 | locator.click() |
| 网络拦截 | page.route() |
| 截图 | page.screenshot() |
| 录屏 | browser.new_context(record_video_dir=…) |
三、一个最"干净"的 Playwright Python 示例
⚠️ 注意:这里没有 pytest,没有 fixture,没有 POM
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto("https://example.com")
print(page.title())
page.click("text=More information")
browser.close()
这段代码里发生了什么?
| sync_playwright() | 启动 Playwright 运行时 |
| p.chromium.launch() | 启动 Chromium 浏览器 |
| new_page() | 新建一个标签页 |
| goto() | 打开 URL |
| title() | 获取页面标题 |
| click() | 点击元素 |
| close() | 关闭浏览器 |
👉 这就是 playwright 模块最原始、最真实的使用方式
四、playwright 模块的两种 API
Playwright Python 模块提供了两套 API:
1️⃣ 同步 API(推荐入门)
from playwright.sync_api import sync_playwright
- 写法直观
- 符合 Python 直觉
- 本专栏默认使用
2️⃣ 异步 API(进阶)
from playwright.async_api import async_playwright
- 基于 asyncio
- 适合高并发场景
- 学习成本更高
📌 结论:
学 playwright 模块本身,先从 sync_api 开始。
五、Playwright vs Selenium(Python 视角)
| 模块定位 | 浏览器驱动 | 浏览器控制 |
| 启动方式 | WebDriver 进程 | 内置浏览器引擎 |
| 等待机制 | 手动写 time.sleep | 自动等待 |
| 元素定位 | find_element(By.XPATH) | page.get_by_role() |
| iframe | 复杂 | 原生支持 |
| 网络拦截 | 弱 | 强 |
| Python 体验 | 偏 Java 风格 | 偏 Pythonic |
✅ Playwright 的 Python 模块设计更现代、更"Python 化"
六、Playwright 模块的核心对象关系(重点)
#mermaid-svg-DKQmnhbvSVAoHPF7{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-DKQmnhbvSVAoHPF7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-DKQmnhbvSVAoHPF7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-DKQmnhbvSVAoHPF7 .error-icon{fill:#552222;}#mermaid-svg-DKQmnhbvSVAoHPF7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-DKQmnhbvSVAoHPF7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-DKQmnhbvSVAoHPF7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-DKQmnhbvSVAoHPF7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-DKQmnhbvSVAoHPF7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-DKQmnhbvSVAoHPF7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-DKQmnhbvSVAoHPF7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-DKQmnhbvSVAoHPF7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-DKQmnhbvSVAoHPF7 .marker.cross{stroke:#333333;}#mermaid-svg-DKQmnhbvSVAoHPF7 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-DKQmnhbvSVAoHPF7 p{margin:0;}#mermaid-svg-DKQmnhbvSVAoHPF7 g.classGroup text{fill:#9370DB;stroke:none;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-DKQmnhbvSVAoHPF7 g.classGroup text .title{font-weight:bolder;}#mermaid-svg-DKQmnhbvSVAoHPF7 .cluster-label text{fill:#333;}#mermaid-svg-DKQmnhbvSVAoHPF7 .cluster-label span{color:#333;}#mermaid-svg-DKQmnhbvSVAoHPF7 .cluster-label span p{background-color:transparent;}#mermaid-svg-DKQmnhbvSVAoHPF7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-DKQmnhbvSVAoHPF7 .cluster text{fill:#333;}#mermaid-svg-DKQmnhbvSVAoHPF7 .cluster span{color:#333;}#mermaid-svg-DKQmnhbvSVAoHPF7 .nodeLabel,#mermaid-svg-DKQmnhbvSVAoHPF7 .edgeLabel{color:#131300;}#mermaid-svg-DKQmnhbvSVAoHPF7 .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-DKQmnhbvSVAoHPF7 .label text{fill:#131300;}#mermaid-svg-DKQmnhbvSVAoHPF7 .labelBkg{background:#ECECFF;}#mermaid-svg-DKQmnhbvSVAoHPF7 .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-DKQmnhbvSVAoHPF7 .classTitle{font-weight:bolder;}#mermaid-svg-DKQmnhbvSVAoHPF7 .node rect,#mermaid-svg-DKQmnhbvSVAoHPF7 .node circle,#mermaid-svg-DKQmnhbvSVAoHPF7 .node ellipse,#mermaid-svg-DKQmnhbvSVAoHPF7 .node polygon,#mermaid-svg-DKQmnhbvSVAoHPF7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-DKQmnhbvSVAoHPF7 .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-DKQmnhbvSVAoHPF7 g.clickable{cursor:pointer;}#mermaid-svg-DKQmnhbvSVAoHPF7 g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-DKQmnhbvSVAoHPF7 g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-DKQmnhbvSVAoHPF7 .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-DKQmnhbvSVAoHPF7 .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-DKQmnhbvSVAoHPF7 .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-DKQmnhbvSVAoHPF7 .dashed-line{stroke-dasharray:3;}#mermaid-svg-DKQmnhbvSVAoHPF7 .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-DKQmnhbvSVAoHPF7 #compositionStart,#mermaid-svg-DKQmnhbvSVAoHPF7 .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-DKQmnhbvSVAoHPF7 #compositionEnd,#mermaid-svg-DKQmnhbvSVAoHPF7 .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-DKQmnhbvSVAoHPF7 #dependencyStart,#mermaid-svg-DKQmnhbvSVAoHPF7 .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-DKQmnhbvSVAoHPF7 #dependencyStart,#mermaid-svg-DKQmnhbvSVAoHPF7 .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-DKQmnhbvSVAoHPF7 #extensionStart,#mermaid-svg-DKQmnhbvSVAoHPF7 .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-DKQmnhbvSVAoHPF7 #extensionEnd,#mermaid-svg-DKQmnhbvSVAoHPF7 .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-DKQmnhbvSVAoHPF7 #aggregationStart,#mermaid-svg-DKQmnhbvSVAoHPF7 .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-DKQmnhbvSVAoHPF7 #aggregationEnd,#mermaid-svg-DKQmnhbvSVAoHPF7 .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-DKQmnhbvSVAoHPF7 #lollipopStart,#mermaid-svg-DKQmnhbvSVAoHPF7 .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-DKQmnhbvSVAoHPF7 #lollipopEnd,#mermaid-svg-DKQmnhbvSVAoHPF7 .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-DKQmnhbvSVAoHPF7 .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-DKQmnhbvSVAoHPF7 .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-DKQmnhbvSVAoHPF7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-DKQmnhbvSVAoHPF7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-DKQmnhbvSVAoHPF7 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Playwright
+chromium
+firefox
+webkit
Browser
+new_page()
+close()
BrowserContext
+new_page()
+add_cookies()
Page
+goto()
+click()
+fill()
这是你必须记住的四层结构:
Playwright
└── Browser
└── BrowserContext
└── Page
👉 所有 API 都围绕这四个对象展开
七、为什么你要"从模块学起"?
很多教程的问题是:
一上来就 pytest + fixture + POM
结果你学会了:
- ✅ 怎么跑用例
- ✅ 怎么写 fixture
- ❌ 但不知道 page.route() 是什么
- ❌ 不知道 BrowserContext 有什么用
- ❌ 不会脱离 pytest 写 Playwright 脚本
✅ 本专栏的目标:
让你离开 pytest 也能熟练使用 playwright 模块
八、本专栏的学习路线
本专栏刻意分成两条线,先模块、后工程:
第一阶段:playwright 模块本身(第 01 ~ 20 篇)
└── 核心对象 / 定位 / 操作 / 等待 / 网络 / 调试 …
第二阶段:工程化应用(第 21 ~ 28 篇)
└── 脚本组织 / pytest 集成 / CI / 实战 …
📌 记住:工程化是"怎么用好",而前 20 篇是"它到底是什么"。
九、小结
- playwright 是一个 Python 模块
- 它的核心是 控制浏览器
- 学习顺序应该是:
- 模块 API
- 浏览器行为
- 工程化(pytest / POM / CI)
📌 下一篇预告:
《安装与第一个纯 Python 脚本》—— 不依赖任何测试框架,纯 python xxx.py 跑通第一个 playwright 程序。
十、思考题
附录:参考资源
- 官方文档:https://playwright.dev/python/
- Python API 参考:https://playwright.dev/python/docs/api/class-playwright
- GitHub:https://github.com/microsoft/playwright-python