Playwright 是一个强大的自动化测试和网页抓取工具,支持 Python 的同步和异步 API。它提供了 Browser
、BrowserContext
和 Page
三个核心对象,用于控制浏览器、隔离上下文和操作页面。以下是对这三个对象的详细介绍,包括其主要接口、使用场景和示例代码,结合你之前的提问背景(如 locator、get_by_text、get_by_role 等),确保内容清晰、全面且实用。
1. Browser 对象
概述
- 定义:
Browser
是 Playwright 的顶级对象,表示一个浏览器实例(如 Chromium、Firefox 或 WebKit)。 - 用途: 用于启动浏览器、管理浏览器级别的设置(如 headless 模式、代理)和创建
BrowserContext
。 - 创建方式: 通过
playwright.<browser_type>.launch()
创建,例如playwright.chromium.launch()
。
主要接口
- 启动和关闭浏览器:
launch(**kwargs)
: 启动浏览器实例。- 参数:
headless
(布尔,是否无头模式)、slow_mo
(慢速执行,单位毫秒)、proxy
等。
- 参数:
close()
: 关闭浏览器,释放资源。
- 创建上下文:
new_context(**kwargs)
: 创建一个新的浏览器上下文(类似于浏览器的独立会话)。- 参数:
viewport
(视口大小)、user_agent
、locale
、permissions
等。
- 参数:
- 创建页面:
new_page(**kwargs)
: 直接创建一个新页面(隐式创建一个上下文)。
- 浏览器信息:
version
: 获取浏览器版本。browser_type
: 获取浏览器类型(chromium、firefox、webkit)。
使用场景
- 初始化浏览器(headless 或 headed 模式)。
- 配置全局浏览器设置(如代理、下载路径)。
- 管理多个独立会话(通过
BrowserContext
)。
示例代码
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
# 启动 Chromium 浏览器(无头模式)
browser = await p.chromium.launch(headless=False, slow_mo=100)
print(f"Browser version: {browser.version}") # 打印浏览器版本
# 创建新上下文
context = await browser.new_context(
viewport={"width": 1280, "height": 720},
user_agent="MyCustomAgent"
)
# 创建页面
page = await context.new_page()
await page.goto("https://example.com")
print(f"Page title: {await page.title()}")
# 关闭浏览器
await browser.close()
import asyncio
asyncio.run(main())
输出示例:
Browser version: 123.0.6312.122
Page title: Example Domain
2. BrowserContext 对象
概述
- 定义:
BrowserContext
表示一个独立的浏览器会话,类似于浏览器的隐身窗口。每个上下文有自己的 cookies、缓存、localStorage 和页面。 - 用途: 用于隔离测试用例、模拟不同用户会话或设备配置(如不同的视口、语言)。
- 创建方式: 通过
browser.new_context()
或隐式通过browser.new_page()
创建。
主要接口
- 创建和管理页面:
new_page()
: 在当前上下文中创建新页面。pages
: 获取上下文中的所有页面列表。close()
: 关闭上下文及其所有页面。
- 网络和权限控制:
set_default_timeout(timeout)
: 设置默认操作超时(毫秒)。grant_permissions(permissions, origin)
: 授予权限(如 geolocation、notifications)。clear_cookies()
: 清除上下文中的 cookies。add_cookies(cookies)
: 添加自定义 cookies。route(url, handler)
: 拦截和修改网络请求。
- 事件监听:
on("page")
: 监听新页面(如弹出窗口)。on("request")
: 监听网络请求。on("response")
: 监听网络响应。
使用场景
- 模拟不同用户的登录会话(不同 cookies)。
- 测试不同设备配置(视口、user-agent)。
- 拦截和模拟网络请求(mock API 响应)。
- 管理弹出窗口或多标签页。
示例代码
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
# 创建上下文,模拟移动设备
context = await browser.new_context(
viewport={"width": 375, "height": 667}, # iPhone 6 尺寸
is_mobile=True,
user_agent="Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X)"
)
# 设置默认超时
context.set_default_timeout(5000)
# 拦截网络请求
async def handle_route(route):
await route.fulfill(status=200, body="Mocked response")
await context.route("**/api/**", handle_route)
# 创建页面
page = await context.new_page()
await page.goto("https://example.com")
# 监听新页面(如弹出窗口)
async def handle_popup(popup):
print(f"New page opened: {await popup.title()}")
context.on("page", handle_popup)
# 模拟点击可能触发弹出窗口的元素
# await page.click("a[target='_blank']")
# 打印上下文中的页面数量
print(f"Open pages: {len(context.pages)}")
# 关闭上下文
await context.close()
await browser.close()
import asyncio
asyncio.run(main())
输出示例:
Open pages: 1
3. Page 对象
概述
- 定义:
Page
表示单个浏览器页面(标签页),是最常用的对象,用于与网页内容交互。 - 用途: 执行导航、元素查找、用户操作(如点击、输入)、截图、录制视频等。
- 创建方式: 通过
context.new_page()
或browser.new_page()
创建。
主要接口
- 导航:
goto(url, **kwargs)
: 导航到指定 URL。- 参数:
timeout
,wait_until
(domcontentloaded, load, networkidle)。
- 参数:
reload()
: 刷新页面。go_back()
,go_forward()
: 页面历史导航。
- 元素查找(结合你之前的 locator 问题):
locator(selector)
: 使用 CSS 或 XPath 选择器查找元素。get_by_role(role, **kwargs)
: 按 ARIA 角色查找(见你之前的get_by_role
提问)。get_by_text(text, exact=False)
: 按文本内容查找(见你之前的get_by_text
问题)。get_by_label(label)
: 按表单标签查找。get_by_placeholder(placeholder)
: 按占位符查找。get_by_test_id(test_id)
: 按data-testid
属性查找。
- 用户交互:
click(selector)
: 点击元素。fill(selector, value)
: 填充表单输入。check(selector)
,uncheck(selector)
: 操作复选框。type(selector, value)
: 模拟逐字输入。press(selector, key)
: 模拟按键(如 Enter)。
- 内容操作:
content()
: 获取页面 HTML 内容。set_content(html)
: 设置页面 HTML(见你之前的set_content
示例)。text_content(selector)
: 获取元素文本内容。inner_text(selector)
: 获取元素可见文本。evaluate(expression, arg)
: 在页面执行 JavaScript。
- 页面信息:
title()
: 获取页面标题。url
: 获取当前 URL。screenshot(path)
: 截取页面截图。pdf(path)
: 生成页面 PDF(仅 Chromium)。
- 事件监听:
on("load")
: 页面加载完成。on("console")
: 监听控制台消息。on("dialog")
: 处理弹窗(如 alert、confirm)。
- 等待机制:
wait_for_selector(selector)
: 等待元素出现。wait_for_timeout(timeout)
: 等待指定时间。wait_for_load_state(state)
: 等待页面加载状态。
使用场景
- 导航和页面操作(如点击按钮、填写表单)。
- 元素查找和验证(结合
get_by_text
,get_by_role
)。 - 截图、录制视频或生成 PDF。
- 执行 JavaScript 或处理动态内容。
示例代码(结合你之前的 locator 问题)
以下示例整合了你之前的提问(get_by_text
, get_by_role
, 属性和子节点打印):
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
# Browser: 启动浏览器
browser = await p.chromium.launch(headless=False)
# BrowserContext: 创建上下文,模拟特定设备
context = await browser.new_context(
viewport={"width": 1280, "height": 720}
)
# Page: 创建页面并设置内容
page = await context.new_page()
html = """
<div class="first" role="region">Hello <span>world</span></div>
<button role="button" aria-label="Submit">Click me <span>world</span></button>
"""
await page.set_content(html)
# 使用 get_by_text 查找(参考你之前的提问)
locator_text = page.get_by_text("world", exact=True)
text = await locator_text.text_content()
print("get_by_text result:", text) # 输出: world
# 使用 get_by_role 查找按钮(参考你之前的 get_by_role 提问)
locator_role = page.get_by_role("button", name="Submit")
button_text = await locator_role.text_content()
print("get_by_role button text:", button_text) # 输出: Click me world
# 打印按钮的属性(参考你第一个问题)
attributes = await locator_role.evaluate(
"""element => {
const attrs = {};
for (const attr of element.attributes) {
attrs[attr.name] = attr.value;
}
return attrs;
}"""
)
print("Button attributes:", attributes)
# 打印按钮的子节点(参考你第二个问题)
children = await locator_role.evaluate(
"""element => {
const childrenArray = [];
for (const child of element.children) {
childrenArray.push({
tagName: child.tagName,
textContent: child.textContent.trim(),
className: child.className || 'none'
});
}
return childrenArray;
}"""
)
print("Button children:")
for i, child in enumerate(children):
print(f"Child {i + 1}: Tag = {child['tagName']}, Text = {child['textContent']}, Class = {child['className']}")
# 截图页面
await page.screenshot(path="screenshot.png")
# 关闭上下文和浏览器
await context.close()
await browser.close()
import asyncio
asyncio.run(main())
输出示例:
get_by_text result: world
get_by_role button text: Click me world
Button attributes: {'role': 'button', 'aria-label': 'Submit'}
Button children:
Child 1: Tag = SPAN, Text = world, Class = none
结合你之前的问题
- get_by_text 问题(world\n Hello\n):
- 如之前分析,
get_by_text("world")
可能选中父<div>
,导致包含额外文本。示例中通过exact=True
或更具体的 locator(如span:text("world")
)解决。
- get_by_role:
- 示例中使用
get_by_role("button", name="Submit")
展示了如何定位具有明确 ARIA 角色的元素,比get_by_text
更可靠。
- 属性和子节点:
- 使用
evaluate()
提取属性和子节点,延续你之前的逻辑,确保一致性。
关键注意事项
- 异步 vs 同步:
- 示例使用异步 API(
async_playwright
),因为你之前使用了await
。同步 API 类似,只需替换为sync_playwright
并移除await
和async
关键字。 - 同步示例:
python 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()) browser.close()
- 超时和等待:
- 使用
set_default_timeout
或wait_for_selector
确保操作健壮性,避免元素未加载的错误。 - 示例:
await page.wait_for_selector("div.first", timeout=5000)
- 错误处理:
- 检查 locator 是否找到元素:
python if await locator.count() > 0: text = await locator.text_content() else: print("No elements found")
- Playwright 版本:
- 确保使用最新版本(
pip install --upgrade playwright
)以获取最新的 locator 支持(如get_by_role
的增强功能)。 - 调试:
- 使用
page.screenshot()
或page.on("console", lambda msg: print(msg.text))
调试页面状态。 - 检查 locator 选中的元素:
python tag = await locator.evaluate("el => el.tagName") print(f"Selected tag: {tag}")
在 Playwright 的 Python API 中,Locator
类是用于定位和操作网页元素的核心工具。它提供了一种灵活且强大的方式来选择 DOM 元素,并支持多种交互操作(如点击、获取文本、提取属性等)。结合你之前的提问(关于 get_by_text
、get_by_role
、打印属性和子节点等),我将详细介绍 Locator
类的功能、主要接口、使用场景,并提供针对性示例,展示如何解决你之前遇到的问题(如 get_by_text
输出意外换行符)以及如何与 Browser
、BrowserContext
和 Page
配合使用。
4. Locator 类
- 定义:
Locator
表示页面上的一组元素(可以是一个或多个),通过选择器(如 CSS、XPath)或 Playwright 特有的定位方法(如get_by_role
、get_by_text
)创建。 - 用途: 用于定位元素、执行交互(如点击、输入)、获取元素属性或内容,以及处理动态内容。
- 创建方式:
- 通过
Page
对象的定位方法创建,例如page.locator(selector)
、page.get_by_role(role)
、page.get_by_text(text)
。 - 通过
Locator
对象的进一步筛选,例如locator.locator(selector)
。 - 特点:
- 惰性求值:
Locator
不会立即查询 DOM,而是等到执行操作(如click()
或text_content()
)时才解析。 - 动态更新: 支持处理动态加载的元素,自动重新查询 DOM。
- 链式定位: 支持嵌套定位(如
locator.locator("span")
)。 - 多元素支持: 可以处理匹配多个元素的场景(如
locator.nth(0)
或locator.all()
)。
1. 主要接口
以下是 Locator
类的主要接口,分为几类:定位、交互、内容提取、状态检查和高级操作。
1.1 定位相关
locator(selector, **kwargs)
: 在当前Locator
的范围内进一步筛选子元素。- 参数:
selector
(CSS 或 XPath)、has_text
(筛选包含指定文本的元素)、has
(筛选包含特定子元素的元素)。 - 示例:
locator.locator("span")
选择当前 locator 中的<span>
元素。 nth(index)
: 选择匹配的第 n 个元素(从 0 开始)。- 示例:
locator.nth(0)
获取第一个匹配元素。 first
: 选择第一个匹配元素(等价于nth(0)
)。last
: 选择最后一个匹配元素。filter(**kwargs)
: 根据条件(如has_text
或has
)过滤 locator。- 示例:
locator.filter(has_text="world")
筛选包含 “world” 的元素。 all()
: 返回所有匹配元素的Locator
列表(异步 API 返回List[Locator]
)。count()
: 返回匹配元素的数量。
1.2 交互操作
click(**kwargs)
: 点击元素。- 参数:
timeout
、button
(left、right、middle)、modifiers
(如 Alt、Shift)。 dblclick(**kwargs)
: 双击元素。fill(value, **kwargs)
: 填充输入框。check(**kwargs)
: 勾选复选框或单选按钮。uncheck(**kwargs)
: 取消勾选。type(value, **kwargs)
: 模拟逐字输入。press(key, **kwargs)
: 模拟按键(如 “Enter”、”Tab”)。hover(**kwargs)
: 悬停在元素上。drag_to(target, **kwargs)
: 拖动元素到目标位置。
1.3 内容和属性提取
text_content(**kwargs)
: 获取元素的文本内容(包括所有子节点,规范化换行符)。inner_text(**kwargs)
: 获取元素的可见文本(不包括隐藏元素)。inner_html(**kwargs)
: 获取元素的 HTML 内容。get_attribute(name, **kwargs)
: 获取指定属性的值(如class
、href
)。input_value(**kwargs)
: 获取输入框的值(如<input>
或<textarea>
)。evaluate(expression, arg=None, **kwargs)
: 在元素上执行 JavaScript 表达式,返回结果。- 示例:
locator.evaluate("el => el.tagName")
获取元素标签名。 evaluate_all(expression, arg=None, **kwargs)
: 对所有匹配元素执行 JavaScript,返回结果列表。
1.4 状态检查
is_visible(**kwargs)
: 检查元素是否可见。is_hidden(**kwargs)
: 检查元素是否隐藏。is_enabled(**kwargs)
: 检查元素是否启用(非 disabled)。is_disabled(**kwargs)
: 检查元素是否禁用。is_checked(**kwargs)
: 检查复选框是否选中。is_editable(**kwargs)
: 检查元素是否可编辑(如输入框)。
1.5 等待机制
wait_for(**kwargs)
: 等待 locator 匹配的元素满足特定状态(如visible
、hidden
)。- 参数:
state
(”attached”、”detached”、”visible”、”hidden”)、timeout
。 wait_for_timeout(timeout)
: 等待指定时间(毫秒)。
1.6 定位器特有方法
get_by_role(role, **kwargs)
: 在当前 locator 中按 ARIA 角色定位子元素。get_by_text(text, exact=False)
: 在当前 locator 中按文本定位子元素。get_by_label(label, exact=False)
: 按表单标签定位。get_by_placeholder(placeholder, exact=False)
: 按占位符定位。get_by_test_id(test_id)
: 按data-testid
属性定位。
2. 使用场景
- 元素定位: 使用 CSS、XPath 或 Playwright 的高级定位方法(如
get_by_role
、get_by_text
)选择元素。 - 动态内容: 处理 AJAX 加载的元素,
Locator
会自动重试直到元素出现。 - 交互测试: 模拟用户操作(如点击、输入、拖放)。
- 数据提取: 获取元素文本、属性或执行 JavaScript 提取复杂数据。
- 多元素处理: 处理列表或表格中的多个匹配元素。
- 结合你之前的问题:
- 打印属性: 使用
evaluate
提取所有属性(如你的第一个提问)。 - 打印子节点: 使用
evaluate
获取子元素信息(如你的第二个提问)。 - 解决
get_by_text
换行问题: 使用更精确的定位或exact=True
避免父元素干扰(如你的第三个提问)。 - 使用
get_by_role
: 结合 ARIA 角色定位(如你的第四提问)。
3. 示例代码
以下示例整合了你的提问背景(get_by_text
、get_by_role
、打印属性和子节点),并展示了 Locator
类的主要接口,涵盖定位、交互、内容提取和状态检查。
示例 1: 基本定位和交互
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
context = await browser.new_context()
page = await context.new_page()
# 设置页面内容(基于你之前的 HTML)
html = """
<div class="first" role="region">Hello <span>world</span></div>
<button role="button" aria-label="Submit">Click me <span>world</span></button>
<input type="text" placeholder="Enter text">
"""
await page.set_content(html)
# Locator: 使用 CSS 选择器定位 div.first
locator = page.locator("div.first")
print("Div text:", await locator.text_content()) # 输出: Hello world
# Locator: 使用 get_by_role 定位按钮
button_locator = page.get_by_role("button", name="Submit")
await button_locator.click() # 模拟点击
print("Button clicked, is enabled?", await button_locator.is_enabled()) # 输出: True
# Locator: 使用 get_by_text 定位 span(解决你之前的换行问题)
span_locator = page.locator("span:text('world')")
print("Span text:", await span_locator.text_content()) # 输出: world
# Locator: 输入框交互
input_locator = page.get_by_placeholder("Enter text")
await input_locator.fill("Test input")
print("Input value:", await input_locator.input_value()) # 输出: Test input
await context.close()
await browser.close()
import asyncio
asyncio.run(main())
输出示例:
Div text: Hello world
Button clicked, is enabled? True
Span text: world
Input value: Test input
示例 2: 打印属性和子节点(结合你之前的提问)
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
context = await browser.new_context()
page = await context.new_page()
html = """
<div class="first" role="region" data-test="example">Hello <span>world</span></div>
<button role="button" aria-label="Submit">Click me <span>world</span></button>
"""
await page.set_content(html)
# Locator: 定位 div.first
locator = page.locator("div.first")
# 打印属性(参考你第一个问题)
attributes = await locator.evaluate(
"""element => {
const attrs = {};
for (const attr of element.attributes) {
attrs[attr.name] = attr.value;
}
return attrs;
}"""
)
print("Div attributes:", attributes) # 输出: {'class': 'first', 'role': 'region', 'data-test': 'example'}
# 打印子节点(参考你第二个问题)
children = await locator.evaluate(
"""element => {
const childrenArray = [];
for (const child of element.children) {
childrenArray.push({
tagName: child.tagName,
textContent: child.textContent.trim(),
className: child.className || 'none'
});
}
return childrenArray;
}"""
)
print("Div children:")
for i, child in enumerate(children):
print(f"Child {i + 1}: Tag = {child['tagName']}, Text = {child['textContent']}, Class = {child['className']}")
await context.close()
await browser.close()
import asyncio
asyncio.run(main())
输出示例:
Div attributes: {'class': 'first', 'role': 'region', 'data-test': 'example'}
Div children:
Child 1: Tag = SPAN, Text = world, Class = none
示例 3: 解决 get_by_text 换行问题(参考你第三个提问)
你的 get_by_text("world")
问题导致输出 world\n Hello\n
,因为它选中了父 <div>
。以下是使用 Locator
精确匹配 <span>
的示例:
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
context = await browser.new_context()
page = await context.new_page()
html = """
<div class="first" role="region">Hello <span>world</span></div>
<div class="second">Hello</div>
"""
await page.set_content(html)
# 使用 get_by_text 精确匹配 span
locator = page.locator("span:text-is('world')") # 使用 text-is 确保精确匹配
text = await locator.text_content()
print("Span text:", text) # 输出: world
# 验证选中的元素
tag = await locator.evaluate("el => el.tagName")
print("Selected tag:", tag) # 输出: SPAN
await context.close()
await browser.close()
import asyncio
asyncio.run(main())
输出示例:
Span text: world
Selected tag: SPAN
示例 4: 使用 get_by_role 和链式定位(参考你第四提问)
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
context = await browser.new_context()
page = await context.new_page()
html = """
<div class="first" role="region">Hello <span>world</span></div>
<button role="button" aria-label="Submit">Click me <span>world</span></button>
"""
await page.set_content(html)
# 使用 get_by_role 定位按钮
button_locator = page.get_by_role("button", name="Submit")
# 链式定位:获取按钮内的 span
span_locator = button_locator.locator("span:text('world')")
text = await span_locator.text_content()
print("Button span text:", text) # 输出: world
# 检查按钮是否可见
print("Button is visible?", await button_locator.is_visible()) # 输出: True
# 获取按钮的 aria-label 属性
aria_label = await button_locator.get_attribute("aria-label")
print("Button aria-label:", aria_label) # 输出: Submit
await context.close()
await browser.close()
import asyncio
asyncio.run(main())
输出示例:
Button span text: world
Button is visible? True
Button aria-label: Submit
4. 结合 Browser、BrowserContext 和 Page
Locator
通常在 Page
对象上创建,并与 Browser
和 BrowserContext
配合使用。以下是典型工作流程:
- Browser: 启动浏览器(
playwright.chromium.launch()
)。 - BrowserContext: 创建隔离会话(
browser.new_context()
),设置视口、cookies 等。 - Page: 创建页面(
context.new_page()
),进行导航(page.goto()
)。 - Locator: 在页面上定位元素(
page.locator()
、page.get_by_role()
等),执行交互或提取数据。
示例:完整工作流程
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
# Browser: 启动 Chromium
browser = await p.chromium.launch(headless=False)
# BrowserContext: 创建上下文,设置视口
context = await browser.new_context(viewport={"width": 1280, "height": 720})
# Page: 创建页面并导航
page = await context.new_page()
await page.goto("https://example.com")
# Locator: 定位所有 <a> 标签
link_locator = page.locator("a")
count = await link_locator.count()
print(f"Found {count} links")
# 遍历所有链接并打印 href
for i in range(count):
href = await link_locator.nth(i).get_attribute("href")
text = await link_locator.nth(i).text_content()
print(f"Link {i + 1}: Text = {text}, Href = {href}")
# 截图
await page.screenshot(path="example.png")
await context.close()
await browser.close()
import asyncio
asyncio.run(main())
输出示例:
Found 1 links
Link 1: Text = More information..., Href = https://www.iana.org/domains/example
5. 解决你之前的问题
以下是如何使用 Locator
类解决你之前的问题:
- 打印所有属性(第一个问题):
- 使用
locator.evaluate()
获取元素属性:python attributes = await locator.evaluate( """element => { const attrs = {}; for (const attr of element.attributes) { attrs[attr.name] = attr.value; } return attrs; }""" )
- 打印子节点(第二个问题):
- 使用
locator.evaluate()
获取子元素信息:python children = await locator.evaluate( """element => { const childrenArray = []; for (const child of element.children) { childrenArray.push({ tagName: child.tagName, textContent: child.textContent.trim(), className: child.className || 'none' }); } return childrenArray; }""" )
- get_by_text 换行问题(第三个问题):
- 使用
page.locator("span:text-is('world')")
或page.get_by_text("world", exact=True)
精确匹配<span>
,避免选中父元素。
- get_by_role(第四问题):
- 使用
page.get_by_role("button", name="Submit")
定位具有明确 ARIA 角色的元素,结合locator
方法进一步筛选子元素。
6. 注意事项
- 异步 vs 同步:
- 示例使用异步 API(
async_playwright
),因为你之前的代码使用了await
。同步 API 类似,只需使用sync_playwright
并移除await
和async
。 - 同步示例:
python from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch(headless=False) page = browser.new_page() page.set_content('<div>Hello <span>world</span></div>') locator = page.locator("span:text('world')") print(locator.text_content()) # 输出: world browser.close()
- 精确定位:
- 使用
exact=True
或:text-is()
避免get_by_text
选中父元素。 - 使用
locator.filter(has_text="world")
或locator.locator("span")
精确筛选。 - 等待机制:
- 对动态内容,使用
await locator.wait_for(state="visible")
确保元素可用。 - 错误处理:
- 检查元素是否存在:
python if await locator.count() > 0: text = await locator.text_content() else: print("No elements found")
- 调试:
- 验证选中的元素:
python tag = await locator.evaluate("el => el.tagName") print(f"Selected tag: {tag}")
- 使用
page.screenshot()
或locator.highlight()
(仅同步 API)调试定位。 - Playwright 版本:
- 确保使用最新版本(
pip install --upgrade playwright
)以支持最新的 locator 功能(如:has()
、:text-is()
)。
7. 总结
- Browser: 管理浏览器实例,适合全局配置和上下文创建。
- BrowserContext: 隔离会话,模拟不同用户或设备,管理 cookies 和网络请求。
- Page: 最常用的对象,用于页面导航、元素查找和用户交互,结合
get_by_role
、get_by_text
等实现你之前的 locator 需求。 - Locator: 提供定位、交互、内容提取和状态检查的强大接口,支持 CSS、XPath 和 Playwright 特有的定位方法(如
get_by_role
、get_by_text
)。 Locator
与 Browser、Context、Page 的关系:Locator
在Page
上创建,依赖BrowserContext
的会话隔离和Browser
的全局配置。- 提取属性和子节点(使用
evaluate
)。 - 结合
get_by_role
和链式定位实现复杂需求。 - 示例: 提供了多个示例,覆盖定位、交互、属性和子节点提取,适配你的 HTML 和提问背景。