Python Playwright学习笔记(一)

一、简介

1.1Playwright 是什么?

它是微软在 2020 年初开源的新一代自动化测试工具,其功能和 selenium 类似,都可以驱动浏览器进行各种自动化操作。

1.2、特点是什么

  • 支持当前所有的主流浏览器,包括 chrome、edge、firefox、safari;
  • 支持跨平台多语言:支持Windows、Linux、macOS;
  • 安装和配置过程简单,会自动安装对应的浏览器和驱动,不需要额外配置 WebDriver 等
  • 更强大的自动化测试配置,支持浏览器有头和无头模式,速度更快、执行更可靠;
  • 支持拦截、修改网络请求,支持文件的上传和下载操作,可以捕获页面截图或生成PDF,支持视频录制功能
  • 强大的工具库:Codegen、Playwright inspector、Trace Viewer。

Codegen:能够记录用户的操作,并将其转化为测试用例,且可以保存为任何语言的测试代码。
Playwright Inspector:可用于检查页面状态,生成精准的选择器,能够逐步执行测试,清晰地查看点击位置,还能探索详细的执行日志。
Trace Viewer:能够捕获所有关键信息,以便在测试失败时进行深入调查。Playwright 的跟踪功能十分强大,包含测试执行过程中的截屏、实时的 DOM 快照、动作资源管理器以及测试的源代码等内容

1.3、Playwright vs seleium对比

序号 比较项目 Playwright Selenium 评分 谁胜出
1 安装难易度 安装较为简便,依赖少 安装过程相对复杂,依赖较多 8:06 Playwright
2 编程语言支持 支持多种主流语言 支持多种主流语言 8:08 平手
3 浏览器兼容性 对主流浏览器兼容性好 对主流浏览器兼容性好 8:08 平手
4 跨平台性 良好的跨平台支持 跨平台性较好 8:07 Playwright
5 文档质量 文档清晰详细 文档较为全面 8:07 Playwright
6 API 设计 简洁直观 相对复杂一些 8:07 Playwright
7 性能 性能较高 性能一般 8:07 Playwright
8 异步支持 优秀的异步处理 异步处理稍显复杂 8:07 Playwright
9 等待机制 灵活多样 有多种等待方式,但稍显复杂 8:07 Playwright
10 元素定位 方便准确 较为准确 8:07 Playwright
11 稳定性 稳定性较好 稳定性一般 8:07 Playwright
12 错误处理 清晰明确 相对复杂 8:07 Playwright
13 并发执行 支持高效并发 并发执行稍弱 8:07 Playwright
14 移动端测试 支持较好 支持一般 8:07 Playwright
15 无头模式支持 支持良好 支持良好 8:08 平手
16 录制功能 有录制功能 录制功能相对较弱 8:07 Playwright
17 社区活跃度 社区逐渐活跃 社区非常活跃 7:08 Selenium
18 插件丰富度 插件相对较少 插件丰富 7:08 Selenium
19 更新频率 更新较快 更新频率一般 8:07 Playwright
20 学习曲线 相对较平缓 学习曲线稍陡 8:07 Playwright
21 对新特性支持 快速支持新特性 支持新特性稍慢 8:07 Playwright
22 代码可读性 代码简洁,可读性高 代码相对复杂,可读性一般 8:07 Playwright
23 与 CI/CD 集成 集成方便 集成相对复杂 8:07 Playwright
24 支持的浏览器版本范围 较广 一般 8:07 Playwright
25 对 WebRTC 的支持 支持较好 支持一般 8:07 Playwright
26 对 HTML5 特性支持 支持良好 支持一般 8:07 Playwright
27 对 CSS3 特性支持 支持良好 支持一般 8:07 Playwright
28 对 JavaScript 框架支持 支持良好 支持一般 8:07 Playwright
29 对前端框架的兼容性 兼容性好 兼容性一般 8:07 Playwright
30 支持的操作系统 多操作系统支持 多操作系统支持 8:08 平手
31 内存占用 相对较低 较高 8:07 Playwright
32 执行速度 速度较快 速度一般 8:07 Playwright
33 对动态页面处理 处理能力强 处理能力一般 8:07 Playwright
34 对 AJAX 请求的处理 处理优秀 处理一般 8:07 Playwright
35 对 iframe 的处理 处理方便 处理稍复杂 8:07 Playwright
36 对表单提交的处理 处理准确 处理一般 8:07 Playwright
37 对弹窗的处理 处理灵活 处理稍复杂 8:07 Playwright
38 对鼠标和键盘事件模拟 模拟自然 模拟稍复杂 8:07 Playwright
39 对文件上传下载的支持 支持良好 支持一般 8:07 Playwright
40 对网络请求拦截的支持 支持较好 支持一般 8:07 Playwright

二、安装Playwright

2.1在Python中安装Playwright相对简单,可以通过pip安装:
pip install playwright

2.2安装完成后,还需要安装浏览器的自动化驱动程序:
playwright install

这将自动下载并安装所需的浏览器驱动程序。

三、使用方法

3.1初始化浏览器

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
browser = p.chromium.launch(headless=False) # headless=False 表示非无头模式

3.2创建一个页面并导航到特定的URL:

page = browser.new_page()
page.goto('https://example.com')

3.3获取元素方法:

以百度输入内容,点击百度一下为例:下面两行是网页源代码:
<input type="text" class="s_ipt" name="wd" id="kw" maxlength="100" autocomplete="off">
<input type="submit" value="百度一下" id="su" class="btn self-btn bg s_btn">

#---------------------1.输入value内容----------------------
根据ID:

方法1.page.fill('input[id="kw"]', 'abc')
方法2.page.fill('xpath=//input[@id="kw"]', 'abc')
方法3:page.locate('#kw').fill('abc')
方法4:ele_input = page.query_selector('input#kw')
ele_input.fill('abc')

根据Name:

page.fill('input[name="wd"]', 'abc')

根据class:

page.fill('input[class="s_ipt"]', 'abc')

根据文本内容:
page.click("text=百度一下")
page.get_by_text('百度一下').click()
其他属性:
page.get_by_label('Username') #input aria-label="Username"
page.get_by_alt_text() #alt="提示信息"
page.get_by_placeholder #placeholder="aaaa"
page.get_by_role() #page.get_by_role("button", name="登录").click()
page.get_by_title() #通过标题属性定位元素。 title="登录"
page.get_by_test_id() #根据data-testid属性定位元素(可以配置其他属性)。

#--------------------2.点击百度一下-------------------------------------

方法1:page.click("text=百度一下")
方法2:page.get_by_text('百度一下')
方法3:page.click('button#login_btn')
方法4:btn = page.query_selector("button#login_btn")
btn.click()

更多根据属性获取元素方法,建议看下js selector选择器相关内容

3.4常用功能总结

Playwright 提供了丰富的 API 来操作页面元素和与页面交互。以下是一些常用功能:

1. 页面导航与跳转

page.goto(url, **kwargs): 导航到指定的 URL。
page.reload(): 重新加载当前页面。
page.wait_for_load_state('load'): 等待页面达到指定的加载状态(如 load、networkidle、domcontentloaded 等,默认值是load)。
state状态说明:
‌ DOMContentLoaded‌:当DOM完全加载和解析完成后,此状态触发。这意味着页面的HTML文档已经完全加载,但不包括图片、样式表等资源文件‌
‌ load‌:当整个页面(包括所有依赖资源如图片、脚本等)完全加载完成后,此状态触发。这是默认状态,适用于大多数情况‌
networkidle‌:当网络没有新的请求超过一段时间(通常是500毫秒)时,此状态触发。适用于需要等待网络活动停止的场景‌
使用场景和区别:
‌ DOMContentLoaded‌:适用于需要等待DOM加载完成但不需要等待所有资源加载的场景。例如,当页面上的交互元素已经可用,但图片或其他资源尚未加载完成时。
‌ load‌:适用于需要等待整个页面(包括所有资源)加载完成的场景。这是最常见的使用场景,确保页面完全准备好进行后续操作。
‌ networkidle‌:适用于需要等待网络活动完全停止的场景。例如,在处理大量异步请求后,确保没有新的网络活动影响后续操作。
page.wait_for_timeout(5000) 等待5秒

2. 页面元素查询与操作

page.query_selector(selector): 使用 CSS 选择器查询页面元素。
page.query_selector_all(selector): 使用 CSS 选择器查询所有匹配的页面元素。
element.click(): 模拟点击元素。
element.fill(values): 填充表单元素的值。
element.input(value): 为元素输入文本。
element.press(key, **kwargs): 模拟按键操作。
element.hover(): 将鼠标悬停在元素上。

3. 页面内容获取

page.title(): 获取当前页面的标题。
page.content(): 获取当前页面的outerrHTML内容。
page.evaluate(expression, **kwargs): 在页面上下文中执行 JavaScript 表达式并返回结果。

4. 截图与录屏

page.screenshot(path=None, **kwargs): 截取当前页面的截图。
browser.start_recording(options): 开始录制浏览器操作,生成视频文件。
browser.stop_recording(): 停止录制浏览器操作。

5. 监听浏览器事件

page.on(event, callback): 监听指定类型的事件,并在事件发生时调用回调函数。
page.off(event, callback): 取消监听指定类型的事件。

6. 网络请求拦截与处理

page.route(url, route_handler): 拦截匹配指定 URL 的网络请求,并可以自定义处理逻辑。
route_handler.abort(): 中止拦截到的网络请求。
route_handler.continue_(): 继续拦截到的网络请求。
route_handler.fulfill(response): 使用自定义的响应内容满足拦截到的网络请求。

7. 浏览器上下文管理

browser.new_context(options): 创建一个新的浏览器上下文。
context.close(): 关闭浏览器上下文,释放资源。

8. 选择器

Playwright 使用选择器来定位页面元素。选择器可以是 CSS 选择器、XPath 或其他类型。例如,page.query_selector 方法接受一个选择器作为参数,并返回匹配的第一个元素。

9. 等待策略

Playwright 提供了多种等待策略,如 wait_for_load_state, wait_for_navigation, wait_for_timeout, 和 wait_for_selector 等,以确保在继续执行操作之前页面已加载完成或元素已出现。

10. 调试与日志

browser.new_page(headless=False): 在非无头模式下打开浏览器,方便进行调试。
console.log(message): 在控制台输出日志信息。

11.执行js

page.evaluate('原生态js')

12.获取某个元素内容innerText:

page.text_content(selector)
比如要获取上面截图中的【欢迎登录】四个字:
<h1 data-v-4a3b3bb4="" class="form-title">欢迎登录</h1>
page.text_content('xpath=//h1[@class="form-title"]')

13.获取属性值:page.get_attribute(selector,attr)
比如要获取截图中左边的大图:
<img data-v-3aa1f3cd="" src="//static.revobit.cn/user-center%402.0.0%2Bbe1fa77/img/login-holder.d395120d.jpg" alt="网站展示图片" class="login-holder">

page.get_attribute("xpath=//img[@alt='网站展示图片']",'src')

四、常用示例

4.1.截图及录制视频示例:

截图并保存:page.screenshot(path="screenshot.png")
生成PDF:page.pdf(path='document.pdf')

录制浏览器会话示例:
video_dir = '.'
browser = p.chromium.launch(headless=False, record_video_dir=video_dir)

4.2.关闭弹出对话框示例:

page.on('dialog', async (dialog) => {
console.log(弹出消息框内容:${dialog.message()});
await dialog.dismiss(); // 关闭消息框
});

通过监听page.on('dialog')事件,并使用dialog.dismiss()方法来关闭消息框。这样可以在自动化测试或爬虫过程中处理弹出消息框的情况。

page.on("request", lambda request: print(f"Request: {request.url}"))
page.on("console", lambda message: print(f"Console: {message.text()}"))
page.on("load", lambda: print("Page loaded"))

4.3.拦截和修改网络请求示例:

def handle_request(route, request):
if request.url.contains('example.com'):
route.continue_()
else:
route.abort()

page.route('**', handle_request)

4.4异步操作示例:

from playwright.async_api import async_playwright
import asyncio

async def main():
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
await page.goto("https://www.example.com")
# 在这里可以执行其他异步操作
await browser.close()

asyncio.get_event_loop().run_until_complete(main())

4.5.某滑块站点的登录操作示例:

with sync_playwright() as p:
browser = p.firefox.launch(headless=True) # 关闭无头
context = browser.new_context(
user_agent='Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36',
viewport={'width': 1920, 'height': 1080}
) # 指定user_agent和viewport创建新窗口
page = context.new_page() # 新建标签页
page.goto(self.login_url) # 跳转到指定链接
page.wait_for_timeout(1000) # 等待1秒
# 填充数据
page.fill('css=[id="username"]', username)
page.fill('css=[id="password"]', password)
page.wait_for_timeout(1000) # 等待1秒
# 点击登录
page.click('div.mb-login-btn') # 点击
print('username: {}, password: {}, msg: 点击登录'.format(username, password))
page.wait_for_timeout(2000) # 等待2秒

# 处理滑块
slide_success = False
for i in range(3):
    print('username: {}, password: {}, msg: 滑块识别第{}次尝试'.format(username, password, i))
    try:
        bg = re.search(r'base64,(.*?)"\)', page.get_attribute('.imgBg', 'style')).group(1).strip().replace('&quot', '')  # get_attribute能够根据选择器锁定的标签拿到想要的属性
        bth = page.get_attribute('.imgBtn > img', 'src').split('base64,', 1)[1].strip()
        slide_x_value = self.identify_gap(base64.b64decode(bg), base64.b64decode(bth))
    except Exception as e:
        continue
    
    # 根据x长度移动轨迹 获取拖动按钮位置并拖动
    slider_btn = page.locator("span.v_rightBtn.btn1")  # 定位标签
    box = slider_btn.bounding_box()  # 获取标签大小属性
    page.mouse.move(box['x'] + box['width'] / 2, box['y'] + box['height'] / 2)  # 移动鼠标
    page.mouse.down()  # 按下鼠标
    mov_x = box['x'] + box['width'] / 2 + slide_x_value
    page.mouse.move(mov_x, box['y'] + box['height'] / 2)  # 鼠标按下后滑动距离
    page.mouse.up()  # 松开鼠标
    page.wait_for_timeout(1000)
    
# 点击账号登录
page.click('.xQuery-master-button')
page.wait_for_timeout(3000)
# 保存storage state 到指定的文件
# storage = context.storage_state(path="auth/state.json")
# print(storage)


if '用户中心' not in page.content():  # page.content()获取标签页全部文本
    return False, []
# print({cookie['name']: cookie['value'] for cookie in page.context.cookies()})
cookies_dict = page.context.cookies()  # 获取标签页cookie
# 导出登录信息
# storage = context.storage_state(path=r"C:\Users\Admin\Desktop\auth.json")
# 加载登录信息
# context = browser.new_context(storage_state=r"C:\Users\Admin\Desktop\auth.json")
# print(storage)
browser.close()  # 关闭浏览器

return True, cookies_dict
参考文档:

https://www.cnblogs.com/ranbox/p/18461048
https://blog.csdn.net/shadowtalon/article/details/139311778
https://blog.csdn.net/cat12340/article/details/143685240

官方文档:

https://github.com/microsoft/playwright
https://playwright.dev/python/docs/intro
https://playwright.dev/python/docs/api/class-playwright

posted @   德尔菲殿堂  阅读(189)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示