Skip to content

核心 API 通俗详解

Playwright 最大的特点是 "默认聪明、减少噪音"——很多 Selenium 里必须手写的等待逻辑,Playwright 都帮您自动搞定了。本章用大白话解释您最常用的 API,Python 和 JS 双语言示例并列,按需选用。


一、页面导航

javascript
// JavaScript
await page.goto('https://example.com');
await page.goto('https://example.com', { waitUntil: 'networkidle' });
python
# Python
page.goto("https://example.com")
page.goto("https://example.com", wait_until="networkidle")

waitUntil 参数说明:

含义推荐场景
'commit'收到服务器响应头即算完成,最快很少用
'domcontentloaded'DOM 树构建完成快速导航、不依赖图片
'load'所有资源(图片、CSS)加载完毕中等场景(默认值)
'networkidle'网络请求完全静止超 500msSPA 网站,完全加载

其他导航方法:

javascript
await page.goBack();     // 后退
await page.goForward();  // 前进
await page.reload();     // 刷新

二、Locator 定位元素(Playwright 核心优势)

IMPORTANT

Playwright 的 Locator 是相对于老式 find_element 的革命性改进:

  • 自动等待:操作元素时自动等它出现、可见、可点击,不需要手写 waitFor
  • 自动重试:如果操作失败(比如元素被遮挡),会自动重试
  • 语义化查找:可用文本内容、角色、标签、占位符等查找,不依赖脆弱的 CSS 选择器

常用定位方式

javascript
// JavaScript —— 推荐优先级从高到低

// 1. 按角色(最推荐,语义清晰)
page.getByRole('button', { name: '登录' })
page.getByRole('textbox', { name: '账号' })
page.getByRole('link', { name: '注册' })

// 2. 按文字内容
page.getByText('立即购买')
page.getByText('立即购买', { exact: true })  // 精确匹配

// 3. 按 placeholder(输入框提示文字)
page.getByPlaceholder('请输入手机号')

// 4. 按 label 文字(表单场景极好用)
page.getByLabel('邮箱地址')

// 5. 按 CSS 选择器(传统方式,备用)
page.locator('#username')
page.locator('.btn-primary')
page.locator('button[type="submit"]')

// 6. 按 XPath
page.locator('//input[@name="password"]')
python
# Python(方法名相同,camelCase → snake_case)
page.get_by_role("button", name="登录")
page.get_by_text("立即购买")
page.get_by_placeholder("请输入手机号")
page.get_by_label("邮箱地址")
page.locator("#username")

查找多个元素(返回 Locator 列表)

javascript
// 获取所有匹配的元素
const items = page.locator('.product-item');
const count = await items.count();         // 元素总数
const first = items.first();              // 第一个
const last  = items.last();               // 最后一个
const third = items.nth(2);              // 第三个(0 开始)

// 遍历(filter 方法很好用)
const buttons = page.getByRole('button');
await buttons.filter({ hasText: '购买' }).click();  // 只点含"购买"文字的按钮

三、自动等待机制(告别 sleep)

Playwright 的 Locator 操作(clickfilltype 等)默认自动等待元素满足以下条件再执行:

  • 元素存在于 DOM 中
  • 元素可见(非隐藏)
  • 元素稳定(不在动画中移动)
  • 元素可点击(没被遮挡)
javascript
// 直接点击即可,Playwright 会自动等它可点击
await page.getByRole('button', { name: '提交' }).click();
// 等价于 Selenium 里:
// wait.until(EC.element_to_be_clickable(...)); element.click();

手动等待(特殊情况才用)

javascript
// 等特定元素出现
await page.waitForSelector('.success-message');

// 等 URL 变化
await page.waitForURL('**/dashboard');

// 等某个函数返回 true
await page.waitForFunction(() => document.querySelector('#result')?.textContent === '完成');

// 等网络请求完成(常用于点击按钮触发 API 调用后等结果)
const [response] = await Promise.all([
  page.waitForResponse(resp => resp.url().includes('/api/login')),
  page.getByRole('button', { name: '登录' }).click()
]);
const data = await response.json();
python
# Python 版
page.wait_for_selector(".success-message")
page.wait_for_url("**/dashboard")
page.wait_for_function("() => document.querySelector('#result')?.textContent === '完成'")

四、表单操作

javascript
// 输入文字(先清空再填写)
await page.getByLabel('邮箱').fill('user@example.com');

// 模拟真人逐字符输入(更像人类)
await page.getByLabel('密码').pressSequentially('MyPassword123', { delay: 80 });

// 清空输入框
await page.getByPlaceholder('搜索').clear();

// 勾选/取消勾选复选框
await page.getByRole('checkbox', { name: '记住我' }).check();
await page.getByRole('checkbox', { name: '记住我' }).uncheck();

// 选择下拉框
await page.getByRole('combobox', { name: '国家' }).selectOption('CN');
await page.getByRole('combobox').selectOption({ label: '中国' });   // 按文字选

// 上传文件
await page.getByLabel('上传').setInputFiles('path/to/file.jpg');
python
# Python 版
page.get_by_label("邮箱").fill("user@example.com")
page.get_by_label("密码").press_sequentially("MyPassword123", delay=80)
page.get_by_role("checkbox", name="记住我").check()
page.get_by_role("combobox", name="国家").select_option("CN")
page.get_by_label("上传").set_input_files("path/to/file.jpg")

五、键盘与鼠标操作

javascript
// 键盘按键(常用快捷键)
await page.keyboard.press('Enter');
await page.keyboard.press('Control+A');    // 全选
await page.keyboard.press('Control+C');    // 复制
await page.keyboard.press('Escape');

// 鼠标操作
await page.mouse.move(100, 200);           // 移动鼠标
await page.mouse.click(100, 200);         // 在坐标处点击
await page.mouse.dblclick(100, 200);      // 双击
await page.mouse.wheel(0, 300);           // 向下滚动 300 像素

// 悬停(触发 hover 菜单)
await page.getByRole('menuitem', { name: '更多' }).hover();

六、获取元素信息

javascript
// 获取文本内容
const text = await page.getByRole('heading').innerText();

// 获取属性值
const href = await page.locator('a.link').getAttribute('href');
const val  = await page.locator('input#amount').inputValue();  // 输入框的值

// 判断状态
const isVisible = await page.locator('#modal').isVisible();
const isEnabled = await page.getByRole('button').isEnabled();
const isChecked = await page.getByRole('checkbox').isChecked();

七、网络拦截与 Mock(Playwright 独创优势)

这是 Playwright 相对 Selenium 最强大的特性之一:可以在浏览器发出请求之前拦截并修改它

拦截并 Mock API 返回数据

javascript
// 拦截特定 API 请求,返回模拟数据
await page.route('**/api/user/info', async route => {
  await route.fulfill({
    status: 200,
    contentType: 'application/json',
    body: JSON.stringify({ name: '候鸟测试用户', vip: true })
  });
});
python
# Python 版
def handle_route(route):
    route.fulfill(
        status=200,
        content_type="application/json",
        body='{"name": "候鸟测试用户", "vip": true}'
    )
page.route("**/api/user/info", handle_route)

等待特定请求完成

javascript
// 场景:点击"加载更多"后,等待数据接口返回再读取内容
const [response] = await Promise.all([
  page.waitForResponse(resp => resp.url().includes('/api/products') && resp.status() === 200),
  page.getByRole('button', { name: '加载更多' }).click()
]);
const products = await response.json();
console.log(`获取到 ${products.length} 个商品`);

屏蔽广告/不必要的资源(加速页面)

javascript
await page.route('**/*.{png,jpg,gif,webp,svg}', route => route.abort()); // 屏蔽图片
await page.route('**/{ads,analytics,tracker}**', route => route.abort()); // 屏蔽广告

八、Cookie 操作

javascript
// 获取全部 Cookie
const cookies = await context.cookies();
console.log(cookies);

// 注入 Cookie(在打开网页之前注入最佳)
await context.addCookies([
  { name: 'token', value: 'abc123', domain: '.example.com', path: '/' }
]);

// 清除所有 Cookie
await context.clearCookies();
python
# Python 版
cookies = context.cookies()
context.add_cookies([
    {"name": "token", "value": "abc123", "domain": ".example.com", "path": "/"}
])
context.clear_cookies()

九、多标签页操作

javascript
// 监听新标签页打开事件
const [newPage] = await Promise.all([
  context.waitForEvent('page'),            // 等新标签页出现
  page.getByRole('link').click()           // 触发打开新标签页的操作
]);
await newPage.waitForLoadState();
console.log('新标签页标题:', await newPage.title());

// 获取所有已打开的标签页
const allPages = context.pages();
console.log(`共 ${allPages.length} 个标签页`);

// 手动新开一个标签页
const anotherPage = await context.newPage();
await anotherPage.goto('https://www.google.com');

十、iframe 操作

javascript
// 定位 iframe 并在其中操作
const iframe = page.frameLocator('iframe#loginFrame');
await iframe.getByLabel('用户名').fill('my_user');
await iframe.getByRole('button', { name: '登录' }).click();

十一、截图与 PDF

javascript
// 截取全屏
await page.screenshot({ path: 'screenshot.png' });

// 截取全页(包含滚动内容)
await page.screenshot({ path: 'full-page.png', fullPage: true });

// 截取指定元素
await page.locator('#product-card').screenshot({ path: 'product.png' });

// 生成 PDF(仅 Chromium 支持)
await page.pdf({ path: 'report.pdf', format: 'A4' });

十二、执行 JavaScript

javascript
// 在页面内执行 JS,获取返回值
const title = await page.evaluate(() => document.title);

// 传参数给页面内 JS
const itemCount = await page.evaluate(
  selector => document.querySelectorAll(selector).length,
  '.product-item'
);

// 操作 DOM:强制点击被遮挡的元素
await page.evaluate(selector => {
  document.querySelector(selector).click();
}, '#hidden-btn');

// 滚动到页面底部
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));

TIP

API 掌握之后,下一章 实战案例库 提供五个可直接套用的完整业务模板:登录、数据抓取、网络拦截、多账号并发……直接复用!