第 2 章 · 第一个脚本与同步 API
本章目标:吃透同步 API 的对象模型(Playwright → Browser → Context → Page),掌握 goto/click/fill 等基础操作与截图,理解 headless、slow_mo 两个调试开关。
2.1 同步 API 的对象模型
sync_playwright() 返回的入口对象下挂着三层核心对象,理解它们的职责是写出正确脚本的前提:
from playwright.sync_api import sync_playwright
with sync_playwright() as p: # p: Playwright 入口
browser = p.chromium.launch() # Browser: 一个浏览器进程
context = browser.new_context() # Context: 隔离的"浏览器档案"
page = context.new_page() # Page: 一个标签页
page.goto("https://example.com")
browser.close()- Browser:一次
launch()对应一个真实进程,启动成本高; - BrowserContext:相当于一份全新的无痕浏览档案(独立 Cookie/缓存/storage),创建成本极低。这是官方测试隔离方案的基石——第 6 章 pytest 插件就是"每个测试发一个新 context";
- Page:context 里的一个标签页,日常操作的主要入口。
能开多少个 context?
几十上百个都没问题:context 只是同一进程内的轻量隔离单元。需要模拟"多用户同时在线"时,开多个 context 即可,而不是开多个 browser。
2.2 基础操作三部曲
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
# 1) 导航:默认等待到 load 状态
page.goto("https://playwright.dev/python")
# 2) 填写搜索框(fill 会先清空再输入)
search = page.get_by_role("button", name="Search")
search.click()
page.get_by_placeholder("Search docs").fill("locators")
# 3) 回车触发搜索并等待结果页
page.get_by_placeholder("Search docs").press("Enter")
page.wait_for_load_state()
print(page.title())
browser.close()常用交互方法速查:
| 方法 | 用途 |
|---|---|
page.goto(url) | 导航,默认等到 load |
locator.click() | 点击 |
locator.fill(text) | 清空并填入文本(input/textarea) |
locator.press(key) | 按键,如 "Enter"、"Control+a" |
locator.check() / uncheck() | 勾选/取消复选框 |
locator.select_option("value") | 下拉选择 |
2.3 截图:全页、元素与视口
page.goto("https://playwright.dev/python")
# 视口截图(默认)
page.screenshot(path="viewport.png")
# 整页滚动截图
page.screenshot(path="full.png", full_page=True)
# 只截某个元素
page.locator("header").screenshot(path="header.png")截图是排查失败的第一手证据,第 16 章会把它接入 CI 失败工件。
2.4 headless 与 headed
# 无头:没有窗口,速度快,CI 标配
browser = p.chromium.launch()
# 有头:弹出真实窗口,本地调试直观
browser = p.chromium.launch(headless=False)调试利器 slow_mo:给每个操作强制加延迟(毫秒),人眼能跟上页面发生了什么:
browser = p.chromium.launch(headless=False, slow_mo=1000)另一个常被混淆的选项是 launch_persistent_context——它把 user-data-dir 和浏览器启动合并成一步,Cookie 会跨运行持久保存,适合爬虫登录态复用;而普通 new_context() 每次都是干净的无痕档案:
# 持久化上下文:数据写入本地目录,重启不丢
context = p.chromium.launch_persistent_context(
user_data_dir="./my-profile",
headless=False,
)测试里不要用 persistent context
持久化上下文会让测试之间互相污染(上个测试的登录态泄漏到下个测试)。E2E 测试永远用干净的 new_context()。
2.5 本章小结
- 对象层级:Playwright → Browser(进程)→ Context(隔离档案)→ Page(标签页);
- Context 轻量且完全隔离,是多用户模拟与测试隔离的基础;
fill先清空再输入;press用于回车等按键;- 截图三形态:视口 /
full_page=True/ 元素级; headless=False + slow_mo是本地调试黄金组合;持久化上下文别用在测试里。
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. 想模拟"两个用户同时各自登录自己的账号",正确的做法是?
2. page.screenshot(path="a.png") 与 full_page=True 的区别是?
3. 为什么 E2E 测试中不推荐 launch_persistent_context?
4. slow_mo=1000 参数的作用是?
🛠️ 动手实践
- 写脚本访问
https://playwright.dev/python,对 header 元素和整页分别截图,比较两张图。 - 用两个 context 同时分别打开不同网站,交替打印两边的标题,体会"并行会话"。
- 分别用
new_context()和launch_persistent_context(user_data_dir="./t")访问任意站点并设置 localStorage,关闭重开后读取该值,观察持久化差异。
掌握了对象模型后,进入第 3 章:定位器 Locator 与严格模式。