跳到主要内容Playwright 基础教程:元素拖拽、坐标获取与文本提取实战 | 极客日志Python大前端
Playwright 基础教程:元素拖拽、坐标获取与文本提取实战
Playwright 基础教程涵盖元素拖拽操作、元素坐标获取、网页源码抓取及元素文本提取等核心功能。通过演示 drag_and_drop 方法实现跨元素交互,利用 bounding_box 计算元素位置中心点。对比 selenium 说明 page.content() 获取源码方式,并详细解析 locator 提供的多种文本提取方法如 inner_text、text_content 的区别与应用场景,适用于自动化测试与爬虫开发场景。
Playwright 基础教程:元素拖拽、坐标获取与文本提取实战
前言
Playwright 是微软开源的自动化测试工具,支持多种浏览器和语言。在 Web 自动化测试及爬虫开发中,我们经常需要处理复杂的用户交互,如拖拽操作,或者需要获取元素的精确位置信息以及页面内的文本数据。本文将详细介绍如何使用 Playwright 实现元素拖拽、计算元素坐标、获取网页源码以及提取元素内文本,并提供完整的代码示例。
环境准备与连接方式
在使用 Playwright 之前,确保已安装 Python 环境并安装了 playwright 库。可以通过以下命令安装依赖:
pip install playwright
playwright install
Playwright 提供了两种主要的浏览器连接模式:连接到已打开的浏览器或启动新的浏览器实例。
1. 连接已打开的浏览器
这种方式适用于调试场景,可以查看浏览器实际运行状态。通过 CDP (Chrome DevTools Protocol) 端口连接。
from playwright.sync_api import sync_playwright
class BrowserConnection:
def __init__(self):
self.playwright = sync_playwright().start()
browser = self.playwright.chromium.connect_over_cdp("http://127.0.0.1:9223")
self.default_context = browser.contexts[0]
self.page = self.default_context.pages[0]
2. 启动新浏览器实例
这是最常用的方式,适合自动化脚本执行。可以配置无头模式(headless)或可视化模式。
class NewBrowserSession:
def __init__(self, url):
playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False)
context = browser.new_context()
self.page = context.new_page()
self.page.goto(url)
元素拖拽操作 (Drag and Drop)
拖拽是常见的用户交互行为,例如文件上传、排序列表等。Playwright 提供了 drag_and_drop 方法简化此过程。
官方文档说明
该方法将指定元素拖拽到目标元素。内部逻辑会先移动到源元素执行 mousedown,再移动到目标元素执行 mouseup。
基本用法
page.drag_and_drop("#source", "#target")
page.drag_and_drop(
"#source",
"#target",
source_position={"x": 34, "y": 7},
target_position={"x": 10, "y": 20}
)
测试案例
为了验证拖拽功能,我们可以创建一个简单的 HTML 页面进行测试。该页面包含一个可拖动的红色方块和一个绿色的放置区域。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Drag and Drop Test</title>
<style>
#dragElement {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
top: 0;
left: 0;
cursor: move;
}
#dropElement {
width: 200px;
height: 200px;
background-color: green;
margin: auto;
}
</style>
</head>
<body>
<div id="bigdiv">
<div id="dragElement"></div>
<div id="dropElement"></div>
</div>
<script>
const dragElement = document.getElementById('dragElement');
let isDragging = false;
let startOffset = {x: 0, y: 0};
function startDrag(e) {
isDragging = true;
startOffset.x = e.clientX - dragElement.offsetLeft;
startOffset.y = e.clientY - dragElement.offsetTop;
}
function endDrag() {
isDragging = false;
}
function drag(e) {
if (!isDragging) return;
dragElement.style.left = e.clientX - startOffset.x + 'px';
dragElement.style.top = e.clientY - startOffset.y + 'px';
}
dragElement.addEventListener('mousedown', startDrag);
document.addEventListener('mouseup', endDrag);
document.addEventListener('mousemove', drag);
</script>
</body>
</html>
拖拽代码实现
假设上述 HTML 文件保存在本地路径,以下是使用 Playwright 执行拖拽的完整类定义。
from playwright.sync_api import sync_playwright
import os
class DragDropDemo:
def __init__(self, file_path):
self.playwright = sync_playwright().start()
browser = self.playwright.chromium.launch(headless=False)
context = browser.new_context()
self.page = context.new_page()
self.page.goto(f"file://{os.path.abspath(file_path)}")
def drag_and_drop_operate(self):
self.page.drag_and_drop(source="#dragElement", target="#dropElement")
print("拖拽操作完成")
if __name__ == '__main__':
demo = DragDropDemo(r"D:/L_Learning/MyLearningCode/draganddrop.html")
demo.drag_and_drop_operate()
demo.playwright.stop()
注意事项:
在执行拖拽之前,请确保要拖动的元素和目标元素都已经加载完成。如果页面加载较慢,建议使用 wait_for_selector 等待元素出现。
元素坐标获取 (Bounding Box)
在某些自动化场景中,我们需要知道元素在页面上的精确位置,例如点击元素的中心点,或者根据坐标进行截图分析。
bounding_box 方法
bounding_box() 返回一个字典,包含元素的 x, y 坐标以及宽度和高度。
def get_bounding_box(page):
locator = page.locator("#dragElement")
locator.wait_for(state="visible")
box = locator.bounding_box()
print(box)
return box
x: 元素左上角距离视口左侧的距离。
y: 元素左上角距离视口顶部的距离。
width: 元素宽度。
height: 元素高度。
计算中心点
def calculate_center(box):
center_x = box["x"] + box["width"] / 2
center_y = box["y"] + box["height"] / 2
return center_x, center_y
center = calculate_center(get_bounding_box(page))
page.click(f"#{center[0]} #{center[1]}")
在实际使用中,更推荐直接使用 locator.click(),它会自动定位到元素中心。但在某些复杂交互或自定义事件模拟中,手动计算坐标非常有用。
获取网页源码
Playwright 获取网页源代码的方式与 Selenium 类似,但 API 更加现代化。
对比 Selenium
- Selenium:
driver.page_source
- Playwright:
page.content()
代码示例
page_source = page.content()
print(page_source[:500])
应用场景:
对于爬虫开发者来说,获取源码后可以使用正则表达式或 BeautifulSoup 等库提取特定数据。这对于处理动态渲染较少的页面非常高效。
获取元素内文本
在表格数据抓取或表单验证中,提取元素内的文本是核心需求。Playwright 的 Locator 对象提供了多种方法来提取文本,不同的方法适用于不同的场景。
常用方法列表
locator.all_inner_texts(): 返回列表,包含所有匹配元素的内部文本。
locator.all_text_contents(): 返回列表,包含所有匹配元素的全文本内容(含子元素)。
locator.inner_text(): 返回字符串,第一个匹配元素的内部文本。
locator.text_content(): 返回字符串,第一个匹配元素及其所有子元素的全文本内容。
locator.inner_html(): 返回字符串,第一个匹配元素的内部 HTML 代码。
详细区别解析
测试代码
def extract_element_text(page):
locator = page.locator("#bigdiv")
texts1 = locator.all_inner_texts()
print(f"all_inner_texts type: {type(texts1)}, value: {texts1}")
texts2 = locator.all_text_contents()
print(f"all_text_contents type: {type(texts2)}, value: {texts2}")
text3 = locator.inner_text()
print(f"inner_text type: {type(text3)}, value: {text3}")
text4 = locator.text_content()
print(f"text_content type: {type(text4)}, value: {text4}")
html5 = locator.inner_html()
print(f"inner_html type: {type(html5)}, value: {html5[:100]}...")
最佳实践建议
- 等待策略:在提取文本前,务必确保元素已加载。推荐使用
locator.wait_for(state="visible")。
- 容错处理:如果元素可能不存在,应捕获异常或使用
locator.count() 判断。
- 性能优化:避免一次性提取过多无关文本,尽量缩小选择器范围。
常见问题与解决方案
问题 1:拖拽失败
原因:元素未加载完成或被遮挡。
解决:增加显式等待,使用 page.wait_for_load_state("networkidle")。
问题 2:文本提取为空
原因:使用了 text_content() 但元素被 CSS 隐藏。
解决:尝试改用 inner_text(),它会根据可视性过滤文本。
问题 3:坐标不准
原因:页面滚动导致视口变化。
解决:确保在固定视口下操作,或使用 scroll_into_view_if_needed() 方法。
总结
本文系统讲解了 Playwright 在 Web 自动化中的几个关键功能:
- 元素拖拽:利用
drag_and_drop 轻松模拟鼠标交互,支持自定义偏移量。
- 坐标获取:通过
bounding_box 获取元素几何信息,辅助精确定位。
- 源码获取:使用
page.content() 快速抓取页面 HTML,配合正则进行数据清洗。
- 文本提取:深入对比了
inner_text、text_content 等方法的差异,帮助开发者根据场景选择合适方案。
掌握这些技能将大大提升自动化测试脚本的稳定性和爬虫数据的获取效率。建议在实际项目中结合具体的业务逻辑,灵活运用这些 API 构建健壮的自动化流程。
相关免费在线工具
- curl 转代码
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
- JSON 压缩
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online