playwright基本使用

一,简介
Playwright 官方介绍https://playwright.dev/python/

跨浏览器和平台

  • 跨浏览器。Playwright 支持所有现代渲染引擎,包括 Chromium、WebKit 和 Firefox。
  • 跨平台。在 Windows、Linux 和 macOS 上进行本地测试或在 CI 上进行无头或有头测试。
  • 跨语言。在TypeScript、JavaScript、Python、.NET、Java中使用 Playwright API 。
  • 测试移动网络。适用于 Android 和 Mobile Safari 的 Google Chrome 浏览器的本机移动仿真。相同的渲染引擎适用于您的桌面和云端。

稳定性

  • 自动等待。Playwright 在执行动作之前等待元素可操作。它还具有一组丰富的内省事件。两者的结合消除了人为超时的需要——这是不稳定测试的主要原因。
  • Web优先断言。Playwright 断言是专门为动态网络创建的。检查会自动重试,直到满足必要的条件。
  • 追踪。配置测试重试策略,捕获执行跟踪、视频、屏幕截图以消除薄片。

运行机制

浏览器在不同进程中运行属于不同来源的 Web 内容。Playwright 与现代浏览器架构保持一致,并在进程外运行测试。这使得 Playwright 摆脱了典型的进程内测试运行器的限制。

  • 多重一切。测试跨越多个选项卡、多个来源和多个用户的场景。为不同的用户创建具有不同上下文的场景,并在您的服务器上运行它们,所有这些都在一次测试中完成。
  • 可信事件。悬停元素,与动态控件交互,产生可信事件。Playwright 使用与真实用户无法区分的真实浏览器输入管道。
  • 测试框架,穿透 Shadow DOM。Playwright 选择器穿透影子 DOM 并允许无缝地输入帧。

完全隔离-快速执行

  • 浏览器上下文。Playwright 为每个测试创建一个浏览器上下文。浏览器上下文相当于一个全新的浏览器配置文件。这提供了零开销的完全测试隔离。创建一个新的浏览器上下文只需要几毫秒。
  • 登录一次。保存上下文的身份验证状态并在所有测试中重用它。这绕过了每个测试中的重复登录操作,但提供了独立测试的完全隔离。

强大的工具

  • 代码生成器。通过记录您的操作来生成测试。将它们保存为任何语言。
  • 调试。检查页面、生成选择器、逐步执行测试、查看点击点、探索执行日志。
  • 跟踪查看器。捕获所有信息以调查测试失败。Playwright 跟踪包含测试执行截屏、实时 DOM 快照、动作资源管理器、测试源等等。

二,下载和安装
python 版本要求 python3.7+ 版本。
安装 playwright:

pip install playwright

安装所需的浏览器 chromium,firefox 和 webkit:

playwright install

仅需这一步即可安装所需的浏览器,并且不需要安装驱动包了(解决了selenium启动浏览器,总是要找对应驱动包的痛点)
ps:如果安装报错,提示缺少Visual C++, 解决办法: 安装Microsoft Visual C++ Redistributable 2019

https://aka.ms/vs/16/release/VC_redist.x64.exe
直接点击就可以下载了,下载后直接安装即可。

三,简单使用
Playwright 支持2种运行方式:同步和异步。以下为同步:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)          # 启动 chromium 浏览器
    page = browser.new_page()              # 打开一个标签页
    page.goto("https://www.baidu.com")     # 打开百度地址
    print(page.title())                    # 打印当前页面title
    browser.close()                        # 关闭浏览器对象

如果不习惯with语句,也可以用start() 和stop() 的方式:

from playwright.sync_api import sync_playwright
playwright = sync_playwright().start()

browser = playwright.chromium.launch(headless=False)
page = browser.new_page()
page.goto("https://www.baidu.com/")

browser.close()
playwright.stop()

四:定位元素
playwright 可以通过 CSS selector, XPath selector, HTML 属性(比如 id, data-test-id)或者是 text 文本内容定位元素。

  • Selector 选择器
    操作元素,可以先定位再操作
   # 先定位再操作
    page.locator('#kw').fill("playwright")
    page.locator('#su').click()

也可以直接调用fill 和 click 方法,传Selector选择器

page.fill('#kw', "playwright")
page.click('#su')
  • CSS 或 XPath 选择器
    可以使用xpath 和 css 元素
# CSS and XPath
page.fill('css=#kw', "playwright")
page.click('xpath=//*[@id="su"]')

当 DOM 结构发生变化时,这些选择器可能会中断。长 CSS 或 XPath 链是导致测试不稳定。

  • text 文本选择器
    文本选择器是一个非常实用的定位方式,根据页面上看到的text文本就可以定位了,比如我们经常在selenium中使用xpath 的文本选择器定位
完全匹配文本 //*[text()="百度一下"]
包含某个文本 //*[contains(text(),"百度一下")]

playwright 封装了text文本定位的方式,也可以支持2种文本定位方式

page.click("text=百度一下")  # 模糊匹配
page.click("text='百度一下 '")  # 完全匹配

ps:text=百度一下和 text='百度一下' 的区别:
text=百度一下 没有加引号(单引号或者双引号),模糊匹配,对大小写不敏感
text='百度一下' 有引号,精确匹配,对大小写敏感

  • Selector 选择器组合定位


    image.png

不同的selector可组合使用,用>>连接
form >> [name="wd"] 定位方式等价于

page.locator("form").locator('[name="wd"]')
  • 内置定位器
    这些是 playwright 推荐的内置定位器。
page.get_by_role()通过显式和隐式可访问性属性进行定位。
page.get_by_text()通过文本内容定位。
page.get_by_label()通过关联标签的文本定位表单控件。
page.get_by_placeholder()按占位符定位输入。
page.get_by_alt_text()通过替代文本定位元素,通常是图像。
page.get_by_title()通过标题属性定位元素。
page.get_by_test_id()根据data-testid属性定位元素(可以配置其他属性)

五,操作

  • fill() 输入文字

  • Type 输入
    一个字符一个字符地输入字段,就好像它是一个使用locator.type()的真实键盘的用户。

page.locator('#kw').type('playwright')
  • 鼠标点击 click()
    执行简单的人工点击。
# Generic click
page.get_by_role("button").click()

# Double click
page.get_by_text("Item").dblclick()

# Right click
page.get_by_text("Item").click(button="right")

# Shift + click
page.get_by_text("Item").click(modifiers=["Shift"])

# Hover over element
page.get_by_text("Item").hover()

# Click the top left corner
page.get_by_text("Item").click(position={ "x": 0, "y": 0})

在幕后,这个和其他与指针相关的方法:

1,等待具有给定选择器的元素出现在 DOM 中 (不用自己去写轮询等待了)
2,等待它显示出来,即不为空,不display:none,不visibility:hidden (这个太人性化了,不用去判断元素是否隐藏)
3,等待它停止移动,例如,直到 css 转换完成
4,将元素滚动到视图中 (这个太人性化了,不用自己去滚动了)
5,等待它在动作点接收指针事件,例如,等待直到元素变得不被其他元素遮挡
6,如果元素在上述任何检查期间分离,则重试
由此可见,click() 方法优化了selenium 点击元素的遇到的一些痛点问题,比如元素遮挡,不在当前屏幕,元素未出现在DOM中或隐藏不可见等不可点击的状态。

  • 文件上传
    (1)您可以使用locator.set_input_files()方法选择要上传的输入文件。
    它期望第一个参数指向类型为 的输入元素"file"。数组中可以传递多个文件。
    如果某些文件路径是相对的,则它们将相对于当前工作目录进行解析。空数组清除所选文件。
# Select one file
page.get_by_label("Upload file").set_input_files('myfile.pdf')

# Select multiple files
page.get_by_label("Upload files").set_input_files(['file1.txt', 'file2.txt'])

# Remove all the selected files
page.get_by_label("Upload file").set_input_files([])

# Upload buffer from memory
page.get_by_label("Upload file").set_input_files(
    files=[
        {"name": "test.txt", "mimeType": "text/plain", "buffer": b"this is a test"}
    ],
)

(2)如果不是input输入框,必须点开文件框的情况
可以使用page.expect_file_chooser() 监听到弹出框,在弹出框上输入文件路径

        with self.page.expect_file_chooser() as fc_info:
            self.page.get_by_placeholder("请选择文件").click()
        file_chooser = fc_info.value
        file_chooser.set_files("Upload file")

几个操作方法

file_chooser.element 返回与此文件选择器关联的输入元素。
file_chooser.is_multiple() 返回此文件选择器是否接受多个文件。
file_chooser.page 返回此文件选择器所属的页面。

设置与此选择器关联的文件输入的值。如果其中一些filePaths是相对路径,那么它们将相对于当前工作目录进行解析。对于空数组,清除所选文件。

file_chooser.set_files(files)
file_chooser.set_files(files, **kwargs)

几个参数

files pathlib.Path
no_wait_after 启动导航的操作正在等待这些导航发生并等待页面开始加载。您可以通过设置此标志来选择退出等待。您仅在特殊情况下才需要此选项,例如导航到无法访问的页面。默认为false.
timeout 以毫秒为单位的最长时间,默认为 30 秒,传递0以禁用超时。可以使用browser_context.set_default_timeout()或page.set_default_timeout()方法更改默认值。

(3)高级操作-事件监听filechooser

page.on("filechooser", lambda file_chooser: file_chooser.set_files(r"D:\tou.png"))

# 点击选择文件按钮,会触发 filechooser 事件
page.get_by_label("选择文件").click()

page.on("filechooser", ) 会自动监听filechooser 事件,只要有点击了选择文件按钮,就会自动触发。

  • focus()聚焦给定元素
    对于处理焦点事件的动态页面,您可以使用locator.focus()聚焦给定元素。
page.get_by_label('password').focus()
  • drag_to 拖动
    您可以使用locator.drag_to()执行拖放操作。此方法将:

将鼠标悬停在要拖动的元素上。
按鼠标左键。
将鼠标移动到将接收放置的元素。
松开鼠标左键。

page.locator("#item-to-be-dragged").drag_to(page.locator("#item-to-drop-at"))

如果您想精确控制拖动操作,请使用较低级别的方法,如locator.hover()、mouse.down()、mouse.move()和mouse.up()。

page.locator("#item-to-be-dragged").hover()
page.mouse.down()
page.locator("#item-to-drop-at").hover()
page.mouse.up()

如果您的页面依赖于dragover正在调度的事件,则您至少需要移动两次鼠标才能在所有浏览器中触发它。要可靠地发出第二次鼠标移动,请重复mouse.move()或locator.hover()两次。操作顺序是:悬停拖动元素,鼠标向下,悬停放置元素,第二次悬停放置元素,鼠标向上。

六,等待

  • 强制等待
    time.sleep() 不再使用
    Playwright 在查找元素的时候具有自动等待功能,如果你在调试的时候需要使用等待,你应该使用page.wait_for_timeout(5000) 代替 time.sleep(5)并且最好不要等待超时。
page.wait_for_timeout(5000) 
  • 显示等待
    在延迟加载的页面中,使用locator.wait_for()等待元素可见是很有用的。或者,像locator.click()这样的页面交互会自动等待元素。
# Click triggers navigation
page.get_by_text("Login").click()
# Click will auto-wait for the element
page.get_by_label("User Name").wait_for()

# Click triggers navigation
page.get_by_text("Login").click()
# Fill will auto-wait for element
page.get_by_label("User Name").fill("John Doe")
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,468评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,620评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,427评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,160评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,197评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,334评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,775评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,444评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,628评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,459评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,508评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,210评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,767评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,850评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,076评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,627评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,196评论 2 341