[1291]Playwright教程

Playwright教程(1)— 常用工具简介及对比

使用场景

这种类型的python库有好多种,鼎鼎大名的selenium,还有playwright、Pyppeteer等。

推荐原因

Playwright是由微软的研发团队所开发的一款 Web 自动化测试框架,这个框架具有多平台、跨语言的特点。除了基本的自动化测试能力之外,同时它还具备非常强大的录制功能、追踪功能。以下是 Playwright 与 Selenium 的对比。

由此可见,Playwright 不仅具备 Selenium 多语言、跨平台、多浏览器的优点。相较于 Selenium,Playwright 还有更加强大的优势。

推荐使用的是playwright,有几个原因:

半自动档

这货可以自动帮你写代码,属于半自动档,不像其他的都是手动挡,门槛极低,自动化代码差不多可以完成50 - 90%代码量

运行命令之后,会自动开启一个浏览器窗口,在这个浏览器窗口的所有人工操作,会自动记录下来帮你转为代码,可以极大节省手动代码的时间,以及降低编写爬虫代码的门槛和难度,不用自己逐个去分析页面代码结构,这个功能真的是极好的。

微软出品

什么概念呢,想想vscode,就是是微软从无到有打造起来的免费开源精品。playwright是从2020年开始创建的项目,三年来微软真正投入了资源去打造这个项目,更新稳定且频率不低,这是我们想长期使用一个库或框架的重要考虑点

代码结构清晰,功能齐全,门槛低

这个框架有好几个语言版本:python、Node.js、Java、.net,原生支持同步异步两种方式,而且对比历史与现在的功能会发现,微软是想打造一个傻瓜式的工具,很多功能后台逻辑并不需要使用者过多关注,框架已经在后台自动帮你想好了。比如,自动等待,就是说在做某个操作之前需要有一个前提条件成立才进行,系统会自动等待检查通过,直到超时。举一个具体例子,比如我要系统自动点击某个元素,那么playwright会自动:

确认元素附加到DOM
确认元素是可见的
确认元素是稳定的(Stable)
确认元素没有被其他元素遮挡
确认元素是可点击的

对比这三年的Playwright的更新思路,明显是朝着稳定、使用简单的方向前进,这正是作为用户所想要的,更好聚焦在自动化操作本身,而不是关注后端的很多逻辑。就好比只要学会开汽车就好,并不需要过多关注汽车是如何运行的。

Playwright官网

https://playwright.dev/playwright.dev/

Playwright的Github链接

https://github.com/microsoft/playwright-pythongithub.com/microsoft/playwright-python


Playwright教程(2)— 安装及自动生成代码

安装playwright

pip install playwright

官网推荐使用pip install pytest-playwright来安装,但没必要,会安装playwright及其他一堆测试所用的库,如果只是使用playwright,那么就没必要这样去安装。

自动下载使用的浏览器

playwright install

执行命令以后,会自动下载chromium、firefox以及webkit三种浏览器,存放文件夹路径为(windows环境):

c:\Users\YOURUSERNAME\AppData\Local\ms-playwright\

以上三种浏览器分别对应三种不同内核的浏览器,在爬虫过程中可以自定义选择任意一种浏览器

自动爬虫脚本录制

简单例子,自动完成下列动作:
打开Bing搜索页面,在搜索框中输入“普通青年的网络爬虫之路”,然后点击搜索

在D盘创建一个文件夹crawler,,打开命令行切换到上述目录下,然后运行如下命令:

playwright codegen -o mytest.py --target python -b chromium

命令解释:

codegen 自动生成代码
-o mytest.py 前面-后面是字母o,表示生成代码文件名为mytest.py
--target python 表示生成的代码语言为python
-b chromium 表示使用的浏览器为chromuium内核,如果希望使用另外两种内核,则可以分别改为:
-b firefox 使用浏览器为firefox内核
-b webkit 使用浏览器为webit内核

上述命令运行后,会自动打开一个空白浏览器,以及一个浮动的工具条:

在浏览器的地址栏中输入:http://bing.com,待出现bing的搜索页面内容后,在bing的搜索栏里输入“普通青年的网络爬虫之路”,点击搜索按钮,然后就可以关掉浏览器,录制页面自动生成代码的工作就自动完成。

在刚才新建的文件夹下面,会自动生成mytest.py文件,使用任意代码编辑打开这个文件,内容如下:

from playwright.sync_api import Playwright, sync_playwright, expect
import time  # 手动加入的代码

def run(playwright: Playwright) -> None:
    browser = playwright.chromium.launch(headless=False)
    context = browser.new_context()
    page = context.new_page()
    page.goto("https://cn.bing.com/")
    page.get_by_role("searchbox", name="Enter your search term").click()
    page.get_by_role("searchbox", name="Enter your search term").fill("普通青年的网络爬虫之路")
    page.get_by_role("searchbox", name="Enter your search term").press("Enter")
    time.sleep(10) # 手动加入的代码
    page.close()

    # ---------------------
    context.close()
    browser.close()

with sync_playwright() as playwright:
    run(playwright)

上述代码中标记了手动加入的代码是作者手动加入,为了更好地观察这个自动代码文件运行效果而做的轻微改动(就是让窗口等待10秒后才关掉)

同步或异步

自动代码有同步和异步之分,默认是采用同步,如希望使用异步,则在运行上述命令时有一个后台窗口中,点击下拉菜单勾选Library Async,这个窗口会自动显示操作浏览器后自动生成的代码。


Playwright教程(3)— 基本思路及对象介绍

建议的操作流程

以终为始,那么建议的操作流程简单来看:

先手工模拟一遍操作,让playwright为我们自动创建好部分代码 ——> 再根据实际情况调整代码

这样的话,就可以省下我们很多的时间和脑细胞,尤其是在一些网页元素定位上以及动作上

完整的爬虫过程

接下来思考,一个完整的爬虫动作过程,有利于对后面整个逻辑的理解:

访问指定的网址 ——> 完成一系列的页面操作(比如登录、筛选、点击)——> **浏览器呈现包含想要信息内容的页面 **——> 通过页面数据分析获取最终爬取内容进行保存

浏览器对象

对于代码来说,简单来说就是:

创建浏览器对象 ——> 访问网址 ——> 页面操作(涉及定位及动作) ——> 数据分析 ——> 保存

我们这一节重点看下浏览器对象,查看上节中自动创建的代码,发现有如下内容:

browser = playwright.chromium.launch(headless=False)
context = browser.new_context()
page = context.new_page()

浏览器相关的对象主要有三种:browser、context、Page,这三种分别是包含关系,即browser包含context,context包含page。具体含义及用法如下:

Browser对象

对应一个浏览器实例(Chromium、Firefox或WebKit)
创建:

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

关闭

browser.close()

一个 Browser 可以包含一个或多个 Context

Context对象

浏览器上下文,相当于一个全新的浏览器配置文件,提供了完全的测试隔离,并且零开销。创建一个新的浏览器上下文只需要几毫秒,每个上下文都有自己的Cookie、浏览器存储和浏览历史记录。浏览器上下文允许同时打开多个页面并与之交互,每个页面都有自己单独的状态,一个 BrowserContext 可以包含多个 Page

可以把浏览器上下文看成一个单独的容器,这个容器内的cookie是共同的,可以创建一个或多个page,这些page可以共用cookie,这个思路可以在使用多并发时可以用到

创建

context = browser.new_context()

关闭

context.close()

Page对象

真正访问网页的对象,对应访问的每一个具体页面,可以简单理解为浏览器的选项卡,新建一个page就相当于打开一个新的选项卡,在Page中主要完成与页面元素交互,一个 Page 可以包含多个 Frame

创建

page = context.new_page()

访问网址

page.goto("https://cn.bing.com/")

关闭

page.close()

Frame对象

这个属于html页面范畴,就是一个实际的网页可能由几个Frame页面组成,每个Frame可能都是一个单独的网页

每个页面有一个主框架(page.MainFrame()),也可以有多个子框架,由 iframe 标签创建产生。在playwright中,无需切换iframe,可以直接定位元素

关于对象的介绍部分内容参考了如下网页内容,感谢:一张图理解Playwright 中Browser、 BrowserContext 和Page的关系


Playwright教程(4)— 打开浏览器

本节将重点讲述如何使用playwright打开浏览器,操作playwright全过程可以分为:打开(关闭)浏览器(包括打开新选项卡)、各种网页动作,比如访问网页、输入字符、点击按钮或链接、下载文件等。

打开(关闭)浏览器+打开新的选项卡

同步方式代码模板

何时使用同步,何时使用异步,简单来说(仅仅是简单理解哈),如果希望用多线程,那么使用异步,单线程使用同步。举个简单例子,比如我想爬取300章小说,如果用单线程去爬,那么时间是线性的,爬取每一章节所使用的时间积累起来就是最终所用的总时间;如果用多线程,比如说同时用10个线程去爬,那么理论上总时间就是单线程所用时间的1/10。
相反,如果我只是想获取某一个页面的内容,那么直接单线程就完事

from playwright.sync_api import Playwright, sync_playwright, expect

def run(playwright: Playwright) -> None:
    browser = playwright.chromium.launch(headless=False)
    context = browser.new_context()
    page = context.new_page()

    ###################这里将是操作页面的代码块##################
    pass
    #############################################################    

    page.close()
    context.close()
    browser.close()

with sync_playwright() as playwright:
    run(playwright)

异步方式代码模板

import asyncio
from playwright.async_api import Playwright, async_playwright, expect

async def run(playwright: Playwright) -> None:
    browser = await playwright.chromium.launch(headless=False)
    context = await browser.new_context()
    page = await context.new_page()

    #########################操作页面的代码块#############
    pass
    ####################################################
    await page.close()
    await context.close()
    await browser.close()

async def main() -> None:
    async with async_playwright() as playwright:
        await run(playwright)

asyncio.run(main())

总结一下:
一个完整的playwright流程,就是依次创建browser(浏览器实例)、context(共cookie、session)、page(具体选项卡页面),然后用页面去模拟操作,完成所有的操作后关闭之前创建的三种对象。

打开浏览器时的常用选项

browser相关:

是否无头模式(即是否隐藏浏览器界面)

headless = False # 显示界面,为True时隐藏界面

打开时最大化窗口:

args = ['--start-maximized'] # 还要配合context中设置 no_viewport = True

网络代理:

proxy = {
"server": "[http://127.0.0.1:8080](https://link.zhihu.com/?target=http%3A//127.0.0.1%3A8080)", # 代理服务器的地址
"bypass": "*.[http://bing.com](https://link.zhihu.com/?target=http%3A//bing.com)", # 不使用代理的域名
"username": "Mike", # 代理服务器的用户名
"password": "123456" # 代理服务器的密码
}

指定下载保存路径:

downloads_path = r"d:\"

Context相关:

最大化窗口(与browser的args联合使用)

no_viewport=True

禁用javascript:

java_script_enabled=False

定义打开窗口的具体大小

viewport={ 'width': 1280, 'height': 1024 }

忽略https错误:

ignore_https_errors=True

常用选项的完整示例代码

args = ['--start-maximized'] 
browser = playwright.chromium.launch(headless=False,args=args, downloads_path = r"d:\")
context = browser.new_context(no_viewport=True, ignore_https_errors=True, java_script_enabled=False)

还有些其他的打开选项,未验证,仅供参考:

context相关:

user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0'

viewport: 字典,指定视口的宽度和高度,例如 {“width”: 1280, “height”: 720}。如果不指定,则使用默认的视口大小。

device_scale_factor: 浮点数,指定设备缩放比例,例如 1.5。如果不指定,则使用默认的设备缩放比例。

is_mobile: 布尔值,指定是否模拟移动设备,默认为 False。

has_touch: 布尔值,指定是否支持触摸事件,默认为 False。

java_script_enabled: 布尔值,指定是否启用 JavaScript,默认为 True。

bypass_csp: 布尔值,指定是否绕过内容安全策略,默认为 False。

locale: 字符串,指定浏览器的语言和地区,例如 “en-US” 或 “zh-CN”。如果不指定,则使用默认的语言和地区。

timezone_id: 字符串,指定浏览器的时区,例如 “Asia/Shanghai” 或 “America/New_York”。如果不指定,则使用默认的时区。

geolocation: 字典,指定浏览器的地理位置,包括 latitude(纬度),longitude(经度)和 accuracy(精度),例如 {“latitude”: 31.2304, “longitude”: 121.4737, “accuracy”: 10}。如果不指定,则使用默认的地理位置。

permissions: 列表,指定浏览器的权限,例如 [“geolocation”, “notifications”, “camera”]。如果不指定,则使用默认的权限。

extra_http_headers: 字典,指定浏览器的额外 HTTP 头部,例如 {“x-foo”: “bar”}。如果不指定,则使用默认的 HTTP 头部。

offline: 布尔值,指定是否模拟离线状态,默认为 False。

http_credentials: 字典,指定浏览器的 HTTP 认证,包括 username(用户名)和 password(密码),例如 {“username”: “admin”, “password”: “123456”}。如果不指定,则使用默认的 HTTP 认证。

color_scheme: 字符串,指定浏览器的配色方案,可以是 “dark” 或 “light”。如果不指定,则使用默认的配色方案。

record_video: 字典,指定是否录制浏览器的视频,包括 dir(视频保存的目录)和 size(视频的宽度和高度),例如 {“dir”: “videos/”, “size”: {“width”: 800, “height”: 600}}。如果不指定,则不录制视频。

record_har: 字典,指定是否记录浏览器的 HTTP 归档(HAR),包括 path(HAR 文件的路径)和 omit_content(是否省略响应内容),例如 {“path”: “trace.har”, “omit_content”: False}。如果不指定,则不记录 HAR。

proxy: 字典,指定代理设置,包括 server(代理服务器地址),bypass(要绕过代理的域名列表),username(代理用户名),password(代理密码)

在新的窗口打开链接:

with context.expect_page() as new_page_info:
    page.click('"立即注册"')  # page为已建立的page对象
new_page = new_page_info.value  # 新的page对象
new_page.close()  # 关闭新的窗口

还有一种方法,在当前页面打开新的窗口

with page.expect_popup() as page1_info:
    page.get_by_role("button", name="高级搜索").click()  # page为已建立的page对象
page1 = page1_info.value  # 新的page对象

page1.close()  # 关闭新窗口

Playwright教程(5)— 访问、等待、定位

访问指定页面

page.goto(url , **kwargs)

# url就是网址,需要包含访问协议,比如https://www.bing.com
# **kwargs包括:
# timeout = 10000  # 可选项,单位ms,超时时间,默认30秒,设为0则永不超时
# wait_until = 'load'  # 可选项,等待页面状态符合指定值,默认为load,具体解释参加下方内容

如果想在新的窗口访问链接或url,参照上节中最后的内容

显式等待某个条件成立(直译为断言, assertions)

这句话的意思是,定位元素或执行某个动作之前,或者说执行下一步语句之前,判断必要的条件是否成立,如果不成立会等待直至超时并报错。其实playwright已经内置了很多隐含自动等待,比如最简单的访问某个页面,然后去定位某个元素,默认情况就是wait_until = 'load',就是说当页面处于load状态,那么语句就会往下执行。访问页面后有四个阶段(按先后顺序):commit, load, domcontentloaded, networkidle,默认为load。

  • commit:表示等待页面的commit事件触发,这是playwright独有的一个值,它意味着页面已经接收到了网络响应,并且开始加载文档。这个值比"load"更早触发,因为它不需要等待所有的资源都加载完成。
  • load:表示等待页面的load事件触发,这通常意味着页面的主要资源已经加载完成,但是可能还有一些异步的请求或者渲染在进行中。
  • domcontentloaded:表示等待页面的DOMContentLoaded事件触发,这通常意味着页面的HTML文档已经解析完成,但是可能还有一些样式表或者脚本在加载中。
  • networkidle:表示等待页面的网络空闲,这通常意味着页面没有超过500毫秒的网络活动。

手动设置等待是为了确保接下来的操作可以成立,旧版本里使用了很多类似wait_for_selector的用法,但新版本推荐使用的是expect方法,就是期望某个条件成立,默认超时时间为5秒

下面locator为定位器的意思,理解为按照条件匹配了某个元素,详细内容会在下面内容中展开

AssertionDescription
expect(locator).to_be_checked()Checkbox is checked,复选框可被选中
expect(locator).to_be_disabled()Element is disabled,元素处于禁用状态
expect(locator).to_be_editable()Element is editable,元素为可编辑状态
expect(locator).to_be_empty()Container is empty,容器为空
expect(locator).to_be_enabled()Element is enabled,元素状态为enabled
expect(locator).to_be_focused()Element is focused,元素位于焦点
expect(locator).to_be_hidden()Element is not visible,元素不可见
expect(locator).to_be_visible()Element is visible,元素可见
expect(locator).to_contain_text()Element contains text,元素包含文本
expect(locator).to_have_attribute()Element has a DOM attribute
expect(locator).to_have_class()Element has a class property
expect(locator).to_have_count()List has exact number of children
expect(locator).to_have_css()Element has CSS property
expect(locator).to_have_id()Element has an ID
expect(locator).to_have_js_property()Element has a JavaScript property
expect(locator).to_have_text()Element matches text
expect(locator).to_have_value()Input has a value
expect(locator).to_have_values()Select has options selected
expect(page).to_have_title()Page has a title
expect(page).to_have_url()Page has a URL
expect(response).to_be_ok()Response has an OK status

可自定义一个不符合条件的错误信息:

# 不符合条件超时错误后,提示should be logged in
expect(page.get_by_text("Name"), "should be logged in").to_be_visible()

举例说明,访问bing页面,会根据所在的ip地理位置显示不同版本的页面

page.goto('https://www.bing.com')

try:
    # 可尝试更改'必应'为'bing',看是否会报错
    expect(page, '非中文页面').to_have_title('必应') # 显示的页面标题是否为必应,否则报错:非中文页面
    print('中文页面')
except Exception as e:
    print('进入非中文页面')
    print(e)

可设置全局expect超时时间,默认为5秒

expect.set_options(timeout=10_000)  # 超时为10秒

定位

注意:这是整个playwright使用的关键,正确的定位是后面动作、页面解析的基础以及前提条件

顾名思义,就是定位一个符合条件的元素,方便后面使用这个定位去进行操作。这是重点内容,后续的操作都是围绕定位来展开。

比如页面有一个显示为“Sign in"的按钮,那么就可以这么写一个定位:

locator = page.get_by_role('button', name='Sign in')  # 定位role为button,文本为登录的按钮

locator.click()  # 点击这个定位元素

推荐的定位方法:

其中role包括button, checkbox, heading, link, list, table等标准的html标签元素

举例:

locator = page.get_by_label("Password") # 按照label

locator.fill(password)  # 在上面的password输入框输入密码

locator = page.get_by_placeholder("name@example.com") # 按placeholder

locator.fill("playwright@microsoft.com")

locator = page.get_by_text(re.compile("welcome, john", re.IGNORECASE)  # 按照显示的文本,忽略大小写

expect(locator).to_be_visible() # 在上述定位的元素可见条件下

locator = get_by_alt_text("playwright logo")  # 按照alt文本内容

按照CSS或XPath来定位

# 定位div元素,使用绝对路径表达式
page.locator("/html/body/div")
# 定位h1元素,使用相对路径表达式
page.locator("//div/h1")
# 定位p元素,使用属性谓词表达式
page.locator("//div[@class='container']/p") # 标签之间必须没有其他标签
# 定位a元素,使用文本表达式
page.locator("//div/a[text()='Learn more']")

'''按照id或class名定位'''
page.locator('#s-usersetting-top').click()  # id = s-usersetting-top
page.locator('input#txtStartDate').fill('2022-01-01')  # input中的id为txtStartDate

page.locator('.s-hotsearch-wrapper a')  # class为s-hotsearch-wrapper元素里的a标签

page.locator("//td[@class='vt']")  # td标签中class为vt的元素

# 更复杂的,带正则表达式和过滤的定位
# 在list的所有选择有文本字样Product 2的li,且为add to cart字样的button
page.get_by_role("listitem").filter(has_text=re.compile("Product 2")).get_by_role(
    "button", name="Add to cart"
)
# 也可这么写
page.get_by_role("listitem").filter(
    has=page.get_by_role("heading", name="Product 2")
).get_by_role("button", name="Add to cart").click()
# 还可以这么写
expect(
    page.get_by_role("listitem").filter(
        has=page.get_by_role("heading", name="Product 2")
    )
).to_have_count(1)  # 有product 2字样的li种,第二个元素

详细介绍可以参照官网如下链接
https://playwright.dev/python/d


Playwright教程(6)— 动作

本节接着讲围绕定位锁采取的一系列动作,比如:输入文本、单选、多选、选择下拉框、点击按钮/文本、按下某个按键、上传文件、元素对应焦点、鼠标的拖拽、执行JS脚本等等。

Text input文本输入

对应的是input、textarea、contenteditable等元素

使用上节讲的locator,就非常简单

locator = page.get_by_label("Password")
locator.fill("mypassword")   # 输入文本

Checkboxes and radio buttons 单选和多选

locator = page.get_by_label('I agree to the terms above')
locator.check()

Select options下拉选择

locator = page.get_by_label('Choose a color')
locator.select_option('blue')

Click鼠标单击和双击

locator = page.get_by_role("button")
locator.click()  # 单击

# Double click
page.get_by_text("Item").dblclick() # 双击,前面的page.get_by_text("Item")就是一个locator

# Right click
page.get_by_text("Item").click(button="right")  # left左键 right右键 middle中键

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

# Hover over element
page.get_by_text("Item").hover()  # 把鼠标移到某个locator上

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

click_count:传点击次数,和delay参数结合使用

  • 类型: number
  • 描述: 指定点击次数。默认为 1,可以设置为 2 来模拟双击。
  • 使用场景: 需要模拟双击或其他次数的点击时使用。例如,双击文件列表中的文件来打开它。
page.locator('//input[@id="su"]').click(click_count=3,delay=3_000)

双击还有另一个方便的方法dblclick(),括号中的参数跟click()类似:

delay

  • 类型: number
  • 描述: 设置两次点击之间的延迟时间(毫秒)。默认为 0。
  • 使用场景: 需要模拟用户点击时的自然延迟,比如在双击之间加入短暂的停顿,以模仿真实的用户行为。

timeout:传入超时时间

  • 类型: number
  • 描述: 设置最大等待时间(毫秒),超过此时间后将抛出超时错误。默认为 30000 毫秒(30 秒)。
  • 使用场景: 当你需要限制等待元素变得可点击的时间。例如,在等待元素出现时,你可能不想等待太长时间。
page.get_by_text('#要点击的元素').click(timeout=1_000) #超时时间,默认30s

force=True
表示playwright auto-waiting机制中,当设置 force=True 时,即使元素被其他元素遮挡,Playwright 也会尝试强制点击该元素。这意味着即使有对话框或其他元素遮挡了目标元素,Playwright 也会尝试直接点击目标元素。

  • 类型: bool
  • 描述: 如果为 true,则强制点击元素,即使它被遮挡。默认为 false。
  • 使用场景: 当元素被其他元素遮挡时,仍然需要点击它。例如,如果一个按钮被一个模态对话框遮挡,可能需要强制点击该按钮。
page.get_by_text('#需要点击的元素').click(force=True)

trial=True
表示只进行playwright auto-waiting的等待而不进行click操作

  • 类型: bool
  • 描述: 如果为 true,则不执行实际的点击操作,而是仅尝试查找元素并检查是否可以点击。默认为 false。
  • 使用场景: 需要验证元素是否可以点击,但不执行实际的点击操作。例如,在测试准备阶段,你可能需要检查页面上的所有按钮是否可点击。
page.get_by_text('#要点击的元素').click(trial=True) #点击前检查元素

no_wait_after
表示,一般情况下,如果click操作触发了一个导航事件,那么pw会等待导航结束,但是这样可能导致click一直未结束而失败。这个就是为了避免这种情况发生。

  • 类型: bool
  • 描述: 如果为 true,则点击后不等待页面导航或资源加载完成。默认为 false。
  • 使用场景: 当点击操作不会导致页面重新加载,而只是触发一些异步操作(如 AJAX 请求)时。例如,如果点击按钮只是更新页面的一部分内容而不刷新整个页面。
page.get_by_text('#要点击的元素').click(no_wait_after=True) #点击后不等待页面加载

Press按下指定的键

# Hit Enter
page.get_by_text("Submit").press("Enter")  # locator上按回车键

# Dispatch Control+Right
page.get_by_role("textbox").press("Control+ArrowRight")  # ctrl + 右方向键

# Press $ sign on keyboard
page.get_by_role("textbox").press("$")  # 按下$

上述特殊按键有:

Backquote, Minus, Equal, Backslash, Backspace, Tab, Delete, Escape,
ArrowDown, End, Enter, Home, Insert, PageDown, PageUp, ArrowRight,
ArrowUp, F1 - F12, Digit0 - Digit9, KeyA - KeyZ

可以组合按下指定的键

# <input id=name>
page.locator('#name').press('Shift+A')  # id为name的元素中按下shift + A

# <input id=name>
page.locator('#name').press('Shift+ArrowLeft')

上传

# Select one file
page.get_by_label("Upload file").set_input_files('myfile.pdf')
# page.get_by_label("Upload file")为一个locator,选择一个文件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"}
    ],
)

Focus聚焦

page.get_by_label('password').focus()

Darg and Drop拖拉

效果是先将鼠标移动要操作的locator上,然后按住左键,移动鼠标到目标locator所在位置,松开鼠标

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

# 将一个locator拖到另一个locator上

鼠标移动到指定的locator上

这在处理一些隐藏菜单很有效,鼠标放到菜单上后,菜单显示,然后就可以操作

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

运行JS脚本

这也是一个很有效的手段,比如某个日期输入框是只读的,无法直接录入想要的日期,只能通过日期选择框去选择,而通过日期选择框去选择效率会很低下,这个时候我们只需要通过运行JS脚本将该输入框的只读属性去掉,然后使用input方法录入日期即可

# 将id为txtStartDtate的元素去掉readonly属性
page.evaluate('document.getElementById("txtStartDate").removeAttribute("readonly");')

从上可以看出,有了locator之后,就可以模拟各种人为的操作。


参考:https://zhuanlan.zhihu.com/p/670543329
https://blog.csdn.net/weixin_54696666/article/details/135210002
https://blog.csdn.net/wx17343624830/article/details/130622056

其它参考:https://blog.csdn.net/qq_52758588/article/details/140689176
https://blog.csdn.net/book_dw5189/article/details/136793937

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值