AngeldayAngelday
Home
  • Java
  • MySQL
  • Maven
  • Spring
  • SpringMVC
  • SpringBoot
  • Mybatis-Plus
  • SpringCloud
  • Redis
  • HTML
  • CSS
  • JavaScript
  • Vue
  • React
  • VBA
  • CentOS
  • ApachePOI
  • Python
  • PlayWright
  • 摄影
  • Photoshop
  • Premiere
  • Lightroom
  • Game
  • Anime
Home
  • Java
  • MySQL
  • Maven
  • Spring
  • SpringMVC
  • SpringBoot
  • Mybatis-Plus
  • SpringCloud
  • Redis
  • HTML
  • CSS
  • JavaScript
  • Vue
  • React
  • VBA
  • CentOS
  • ApachePOI
  • Python
  • PlayWright
  • 摄影
  • Photoshop
  • Premiere
  • Lightroom
  • Game
  • Anime
  • Playwright

Playwright

快速入门

1. 简介

Playwright 是微软开发的Web应用的自动化测试框架。

Playwright 可以使用NodeJS和Python语言进行编写。

与Selenium的区别

  1. Selenium 只提供了 web 自动化功能。如果你做自动化测试,需要结合其他自动化测试框架,而 playwright 是面向自动化测试的,除了 web 自动化功能,它也包含了自动化测试的功能框架。
  2. 两者的自动化原理有些差别

2. 安装

pip install playwright

出现以下信息表示安装完成:

C:\Windows\system32>pip install playwright
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple/
Collecting playwright
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/46/4f/9ba607fa94bb9cee3d4beb1c7b32c16efbfc9d69d5037fa85d10cafc618b/playwright-1.55.0-py3-none-win_amd64.whl (35.5 MB)
     ---------------------------------------- 35.5/35.5 MB 6.1 MB/s eta 0:00:00
Collecting pyee<14,>=13 (from playwright)
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/9b/4d/b9add7c84060d4c1906abe9a7e5359f2a60f7a9a4f67268b2766673427d8/pyee-13.0.0-py3-none-any.whl (15 kB)
Collecting greenlet<4.0.0,>=3.1.1 (from playwright)
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/d8/0f/30aef242fcab550b0b3520b8e3561156857c94288f0332a79928c31a52cf/greenlet-3.2.4-cp311-cp311-win_amd64.whl (299 kB)
     ---------------------------------------- 299.1/299.1 kB 6.1 MB/s eta 0:00:00
Collecting typing-extensions (from pyee<14,>=13->playwright)
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl (44 kB)
     ---------------------------------------- 44.6/44.6 kB ? eta 0:00:00
Installing collected packages: typing-extensions, greenlet, pyee, playwright

安装playwright后,运行以下命令来安装浏览器:

playwright install chromium

3. 自动化代码助手

Playwright内置了代码助手,可以自动生成代码。 输入以下命令,即可启动代码助手:

playwright codegen

注意:代码助手主要是记录人对页面的输入,并不能取代人自己写代码,特别是获得页面上的信息的代码。(比如打印标题栏就没有办法自动生成)

page.wait_for_timeout(1000) 单位:ms

4. 跟踪功能

Playwright有个特色功能:跟踪(tracing) 启动跟踪功能后,可以再执行自动化后,通过记录的跟踪数据文件,回看自动化过程中的每个细节。

执行完成后,会再当前工作目录生成一个trace.zip的跟踪数据文件。 查看这个文件有两种方式:

  • 直接访问https://trace.playwright.dev/这个网站,上传跟踪文件。
  • 执行命令playwright show-trace trace.zip,在本地打开查看。

定位

Web界面自动,要对界面进行操作,首先需要定位界面元素。 我们需要让浏览器先定位找到元素,然后才能操作元素。

相对来说,定位元素比后续操作元素更难一些,因为常见操作不是很多,并且是一些固定调用。

比如:

  • 点击元素,click()
  • 输入文本,fill()
  • 获取元素内部文本,inner_text()

Locator对象

Playwright中根据CSS Selector定位元素,就是使用Locator对象。

Page对象的locator方法就是创建一个Locator类型的对象,参数就可以是CSS Selector 表达式。

page.locator("div") # div元素
page.locator("#myId")  # id为myId的元素 
page.locator(".myClass") # class为myClass的元素

根据 tag名、id、class 定位元素

CSS Selector 可以根据HTML元素的标签名、id、class进行定位。

根据tag名选择元素时可以直接写tag名,比如要选择所有的tag名的div元素:

locators = page.locator("div").all()

然后可以获取所有div元素的内部可见文本,可以直接调用all_inner_texts

for one in locators:
    print(one.inner_text())

要获取所有div元素的内部可见文本也可以使用链式调用

texts = page.locator("div").all_inner_texts()

注意:如果locator调用匹配的结果是多个元素,调用针对单个元素的方法,比如inner_text,会有错误抛出:page.locator('div').inner_text()

一个元素可以有多个class类型,多个class类型的值用空格隔开,比如:

<span class="chinese student">张三</span>

注意,这里的span标签有两个class属性,分别是chinese、student,而不是chinese student。 使用代码选择这个元素,可以指定任意一个class属性值,都可以匹配到这个元素。 而不能写成

page.locator(".chinese student")

如果要表示同时具有两个class属性,可以写为:

page.locator(".chinese.student")

如果要表示同时选择两种class属性,可以写为:

page.locator(".chinese,.student")

验证CSS Selector正确选择元素

当然可以写出python代码,然后运行,看是否正确选择元素。但是太麻烦了。

可以直接在浏览器的开发者工具中验证

  • 打开开发者工具
  • 在Elements标签中,同时按Ctrl + F,打开搜索框。这个搜索框是支持css selector的写法的。

匹配多个元素

如果一个locator表达式匹配到多个元素,要获取所有元素的locator对象,要使用all()方法。

locators = page.locator(".plant").all()

有时只需要获得某种表达式对应的元素的数量可以使用count()方法

count = page.locator(".plant").count()

根据结果(也就是匹配的元素数量),可以判断元素是否存在。

有时只需要得到第一个匹配的元素,或者最后一个元素。 可以使用first和last属性。

lct = page.locator(".plant")
print(lct.first().inner_text(), lct.last().inner_text())

也可以通过nth方法,指定索引,获取第几个元素。

lct = page.locator(".plant")
print(lct.nth(0).inner_text(), lct.nth(1).inner_text())

元素内部定位

前面都是通过Page对象调用的locator方法,定位的范围是整个网页。 如果想要在某个元素内部定位,可以通过Locator对象调用locator方法。

# 在#bottom对应元素的范围内寻找标签名为span的元素
lct = page.locator("#bottom")
eles = lct.locator("span").all()
for e in eles:
    print(e.inner_text())

选择子元素和后代元素

HTML中元素内部可以包含其他元素。 如果元素2是元素1的直接子元素。CSS Selector选择子元素的语法是:

元素1 > 元素2

最终选择的元素是元素2。

如果元素2是元素1的后代元素。CSS Selector选择后代元素的语法是:

元素1 元素2

最终选择的元素是元素2。

根据属性选择元素

CSS Selector 可以根据元素的属性来选择元素。 语法是一个方括号[]。 例如选择一个a元素

<a href="https://www.baidu.com">百度</a>

如果要选择href属性为https://www.baidu.com的a元素,可以使用

[href='https://www.baidu.com']

也可以加上标签限制

a[href='https://www.baidu.com']

根据属性选择,也可以不指定属性值:

[href]

CSS还可以选择属性值包含某个字符串的元素:

a[href*="baidu"]

还可以选择属性值为某个字符串开头的元素:

a[href^="https"]

还可以选择属性值为某个字符串结尾的元素:

a[href$="com"]

也可以指定多个属性:

a[href*="baidu"][title="百度"]

按次序选择子节点

CSS Selector 可以选择某个元素的第几个子节点。 语法是:

元素:nth-child(n)

n是一个整数,表示第几个子节点。n从1开始计数。

例如,选择一个div元素的第2个子元素:

div:nth-child(2)

如果要选择一个div元素的第2个子元素,并且这个子元素是一个span元素,可以写为:

div > span:nth-child(2)

也可以选择倒数第几个子元素:

div:nth-last-child(2)

选择父节点

选择相邻兄弟元素

Xpath 定位

XPath(XML Path Language)是由W3C发布的,用来在XML和HTML文档中选择节点的语言。 Playwright也支持使用XPath来定位元素。

Playwright 代码助手生成的定位

Playwright不推荐CSS Selector的定位方式,都是根据HTML网页元素特征的定位,属于开发者的角度。 Playwright更推荐用户角度视觉呈现的定位。

根据文本内容定位

有时想要获取页面中包含某些文字的元素,使用CSS Selector可能比较麻烦,可以使用Page/Locator对象的get_by_text方法。

# 选择所有带有百度一下文字的元素
elements = page.get_by_text("百度一下").all()

匹配文字可以使用正则表达式。例如匹配结尾为下的文字的元素。

import re
elements = page.get_by_text(re.compile("百度一下$")).all()

根据Role定位

web应用有一种标准称之为:ARIA(Accccessible Rich Internet Applications)。 ARIA定义了网页中各种元素的角色,比如按钮、链接、图片、文本、输入框等。 Playwright提供了根据ARIA角色来定位元素的方法。

# 选择所有按钮
elements = page.get_by_role("button").all()

常用视觉定位

根据placeholder属性定位。 可以使用Page/Locator对象的get_by_placeholder方法。

<input type=""text placeholder="captcha"/>
page.get_by_placeholder("captcha",exact=True) # 表示精确匹配

其他视觉定位

可以通过 label 来定位

page.get_by_label("username").fill("ttp")

操作

缺省等待时间

Playwright在定位元素时,如果没有找到这个元素,Playwright在定位元素时,如果没有找到这个元素,Playwright并不会立即抛出错误,而是缺省等待元素时间为30秒。在30秒内,如果元素出现了,就会立即操作成功返回。

元素通用操作

  1. 获取文本内容 通过 locator 对象的 inner_text() 的方法,可以获得内部文本 如果 locator 选择到的元素是多个,可以使用 all_inner_texts(),获取所有匹配的文本,放到列表中返回。 上面这两个方法返回的都是元素内部的可见元素。
  2. 获取隐藏内容 可以使用text_content()或all_text_contents()方法获取单个或多个匹配对象文本。
  3. 获取元素的属性 获取元素的属性值,可以使用Locator对象的get_attribute('属性名')方法。
  4. 获取元素内部HTML Locator对象的inner_html()方法
  5. 等待元素可见 wait_for()等待一个元素的出现
  6. 判断元素是否可见 有时,自动化代码需要根据当前页面中是否存在某些内容,来决定下一步操作。 此时可以使用is_visible()方法

该方法不会等待元素出现,会直接返回 true 或 false

光标动作

  1. 点击 click()方法是单击元素;双击可以使用dbclick()。
  2. 悬停 让光标悬停到某个元素上方,可以使用hover()方法

输入框操作

  1. 文本框输入 单行文本框input 或多行文本框textarea 都可以使用 Locator 对象的 file 方法进行输入。
  2. 文本框清空 要清空单行文本框或多行文本框的内容,可以使用clear方法。

注意:获取input框的内容要使用input_value()方法

  1. 文件输入框 对于html 中有文件类型的输入框,通常用于上传文件。 要设置选中的文件,可以设置 locator 对象的 set_input_files() 方法。
page.locator('input[type=file]')
# 选择单个
lc.set_input_files('d:/1.png')
# 选择多个
lc.set_input_files(['d:/1.png','d:/2.png'])
  1. radio单选/checkbox多选 常见的选择框包括 radio、checkbox、select。 radio 是常见的点选元素
<div id="s _radio">
    <input type="radio" name="teacher" value="小江老师">小江老师<br>
    <input type="radio" name="teacher" value="小雷老师">小雷老师<br>
    <input type="radio" name="teacher" value="小凯老师” checked="checked">小凯老师
</div>

如果要点选 radio 框,可以使用 check() 方法。 如果要取消选择 radio 框,可以使用 uncheck() 方法。 如果要判断 radio 框是否选中,可以使用 is_checked() 的方法。

check框同radio。

  1. select框 可以使用 select 元素对应的 select_option 方法。 对于单选框
page.locator('#ss_single').select_option('小江老师')

这里select_option 参数是选项 option 元素的 value 或者选项文本要完全匹配。

也可以使用关键字参数、index、value、label 指定分别根据索引、 value 属性、选项文本进行匹配。

#根据 索引 选择,从0开始
page.locator('#ss_single').select_option(index=1)
# 根据 value属性 选择
page.locator('#ss_single').select_option(value='小江老师')
#根据 选项文本 选择
page.locator('#ss_single').select_option(label='小江老师')
# 消空所有选择
page.locator('#ss_single').select_option([])

select多选框,方法与上面相同,参数换成列表即可。

page.locator('#ss_single').select_option(value=['小江老师','小王老师'])

对网页的操作

打开网址/刷新/前进/后退 要打开网址/刷新/前进/后退,可以分别调用Page对象的。goto/reload/go_back/go_forward方法。

获取网页HTML 要获取整个网页的 html,可以调用Page的 content() 方法。

title 要获取整个网页的标题栏文本,可以调用Page对象的 title() 方法。

set-viewport-size 要设置页面大小,可以调用Page对象的 set_viewport_size 方法。

#单位是像素
page.set_viewport_size({"width": 640,"height": 480})

frame切换

网页可以嵌入网页,但是 playwright在打开一个网页时,操作范围 缺省是当前 html ,并不包含被嵌入的 html 文档里面的内容。如果想要定位操作被嵌入的 html 文档中的元素,就必须切换操作范围到被嵌入的文档当中。 可以使用Page或Locator对象的frame_locator()方法定位到需要操作的frame。

# 产生一个Frame locator 对象
frame = page.frame_locator("iframe[src='sample1.html']")
# 再 在其内部进行定位
lcs = frame.locator('.plant').a11()
for lc in lcs:
	print(lc.inner_text(timeout=1000))

窗口切换

点击a连接可以跳转到另一个网页,也可以新打开另一个网页。 即使新窗口打开了,这时Page变量对应的还是老窗口,自动化操作,也还是在老窗口进行的,所以需要切换到新窗口。 BoowserContext对象有一个pages属性,里面依次为所有的窗口对应的Page对象。

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

browser = pw.chromium.launch(headless=False)

# 创建BoowserContext对象
context = browser.new_context()
# 通过context创建page
page = context.new_page()
page.goto("https:ur")

#点击连接,打开新窗口
page.locator("a").click()
# 等待2秒
page.wait_for_timeout(2000)

# pages属性是所有窗口的列表
newPage = context.pages[1]

# 打印新旧网页标题
print(newPage.title())
print(page.title())

如果打开了很多窗口,不知道目标的次序号,可以用检查标题的方法。

设置当前tab

想要把某个窗口作为当前活动窗口显示,可以调用这个窗口对象的bring_to_front()方法。

关闭网页窗口

直接调用page对象的close()方法。

冻结窗口

有些元素需要光标移上去才显示。 可以在控制台输入

setTimeout(function(){debugger}, 5000)

截屏

使用Page对象的screenshot()方法。

# 截屏当前页面可见内容,保存到当前工作目录下的ss1.png文件中。
page.screenshot(path='ss1.png')

# 完整截图,页面过长,可以截全图
page.screenshot(path='ss1.png',full_page=True)

也可以只对某一个元素的显示内容进行截屏,使用Locator对象的screenshot方法。

page.locator('input[type=file]').screenshot(path='ss1.png')

拖拽

可以使用page对象的drag_and_drop()方法。 比如选择 span #t1的文本内容,拖拽到输入框里面去

page.locator('#t1').select_text()
page.drag_and_drop('#t1', '[placeholder="captcha"]')

弹出对话框

弹出的对话框有三种类型,分别是 alert(警告信息)、confirm(确认信息)和 prompt(提示输入)。

Alert

alert 就是通知信息,在用户看完信息后点击 ok 就可以了。

# 处理弹出对话框的函数
def handleDlg(dialog):
	page.wait_for_timeout(1000)
	# 点击确认
	dialog.accept()
	print(dialog.message)

# 设置弹出对话框时间回调函数
page.on("dialog", handleDlg)

Confirm

accept()方法相当于点击确认 dismess()相当于点击取消

Prompt

在accept()方法中输入参数字符串,作为要输入的信息

dialog.accept("要输入的内容")