文章目录
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为定位器的意思,理解为按照条件匹配了某个元素,详细内容会在下面内容中展开
Assertion | Description |
---|---|
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() # 点击这个定位元素
推荐的定位方法:
- page.get_by_role() to locate by explicit and implicit accessibility attributes.
- page.get_by_text() to locate by text content.
- page.get_by_label() to locate a form control by associated label’s text.
- page.get_by_placeholder() to locate an input by placeholder.
- page.get_by_alt_text() to locate an element, usually image, by its text alternative.
- page.get_by_title() to locate an element by its title attribute.
- page.get_by_test_id() to locate an element based on its
data-testid
attribute (other attributes can be configured).
其中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