playwright学习笔记
playwright api地址
https://playwright.dev/dotnet/docs/writing-tests
https://mp.weixin.qq.com/s?__biz=MzkxMDM1NDQ0OA==&mid=2247498458&idx=2&sn=a93d4ce571ca5d70a779aae9b596f4ae&source=41#wechat_redirect
https://blog.csdn.net/karl41/article/details/119334673
https://article.itxueyuan.com/ZoLrDw
https://betheme.net/dashuju/96613.html?action=onClick
Python开源自动化工具Playwright安装及介绍使用
它支持主流的浏览器,包含:Chrome、Firefox、Safari、Microsoft Edge 等,同时支持以无头模式、有头模式运行,并提供了同步、异步的 API,可以结合 Pytest 测试框架 使用,并且支持浏览器端的自动化脚本录制。
项目地址:https://github.com/microsoft/playwright-python
官网:https://playwright.dev/
2、Playwright安装
Playwright功能强大,但它的安装步骤,非常简单,只需要 2 步:
第 1 步,安装 playwright-python 依赖库 (需要注意的是,playwright库需要依赖Python3.7+以上)
#此处可能是pip/pip3,或者两者皆可
pip3 install playwright
可以在https://pypi.org/project/playwright/查看它的依赖版本信息。
第 2 步,安装主流的浏览器驱动
这样,会将 Chromeium、Firefox、Webkit 浏览器驱动下载到本地
#安装浏览器驱动(安装过程稍微有点慢,请耐心等待)
python3 -m playwright install
如果想查看Playwright支持的功能, 可以直接在命令行输入:
python3 -m playwright help
1)录制脚本
python3 -m playwright codegen --help
python3 -m playwright codegen --target python -o 'mikezhou.py' -b chromium https://www.baidu.com
命令行输入后会自动打开浏览器,然后可以看见在浏览器上的一举一动都会被自动翻译成代码,如下所示:
最后,自动化脚本会自动生成,保存到文件中mikezhou.py, 且上述所有的人工操作,都会被自动转化成代码:
1.cookies
设计思路
对于一些登录比较复杂的网站,具有反爬虫机制,比如手机验证码、滑块验证等,这时可以通过人工手动登录后,保存cookies到指定文件,以后登录就可以通过加载已保存的cookies实现免登陆啦。
1、打开网站登录页面;
2、设置等待时间,进行手工登录;
3、登录后获取并保存cookies。
from playwright.sync_api import sync_playwright
import json
# 先手动登录,保存Cooies到文件。
def saveCookies():
with sync_playwright() as p:
# 显示浏览器,每步操作等待100毫秒
browser = p.firefox.launch(headless=False, slow_mo=100)
context = browser.new_context()
# context.add_init_script(js)
page = context.new_page()
page.goto('https://cq.meituan.com/', timeout=50000) # 设置超时时间为50s
time.sleep(80) # 此处手动登录,然后到个人信息页再获取cookie
cookies = context.cookies()
print(page.title())
browser.close()
f = open('cookies.txt', 'w')
json.dump(cookies, f)
print('已获取cookies')
time.sleep(2)
browser.close()
saveCookies()#执行函数
playwright手动设置cookies和获取cookies的方法
const browser = await chromium.launch({
headless: false
});
const context = await browser.newContext();
const page = await context.newPage();
context.addCookies([
{
"name": ".AspNetCore.Antiforgery.v2CUd5wyqKo",
"domain": "xxxx.com",
"value": "CfDJ8LY97Wcbz7VCv7_x1JiYm96-2kqovbTwK88qSQBNMPKiYPcwfz9WwDsAT72aQUEaQETi3UFYMh9_Kob9nffYFT0A8QqIe7AB96hrgiW0zntQqwBOJASYccsK8ubkZxa2ZN5darwFzORs5ws7s-8BcHA"
"path": "/"
}
])
await page.goto('https://xxxx.com/');
Playwright选择器
CSS选择器
标签
html元素标签,直接写标签名,如
<button value="title"></button> 1
page.click('button') # 点击标签为button的按钮
page.locator("button").click()
ID
元素中的ID属性,在ID前标识#,如
<input id="user"></input>
page.fill('#user', 'username') # 在id=user的输入框中输入username
page.locator('#main-nav-menu [href="/topics"]').click()
Class
元素中的class属性,在class前标识.,如
<input class="btn" type="button"></input>
1
page.click('.btn') # 点击class为btn的按钮
其他属性
元素中除ID和Class的其他属性,使用[attr<=value>]语法,如
<input type="password"></input>
<input type="checkbox" name="vehicle" value="Bike" checked>I have a bike<br>
page.fill('[type=password]', 'password') # 在具有属性type=password的输入框中输入password
page.click('[checked]') # 点击具有属性checked的按钮
page.locator('[href="/topics"]').click()
多种属性同时使用
上述多种选择器可以同时使用,连在一起写即可,如
page.fill('input[type=password]', 'password') # 在具有属性type=password同时标签为input的输入框中输入passwordpage.click('input.btn') # 点击class为btn同时标签为input的按钮
组合选择器
当元素本身的属性不足以唯一定位到我们想要的元素时,可以使用组合选择器,通过元素的父节点或祖先节点来进行唯一定位,如
<div id="user"><button></button></div><div id="userinfo"><button></button></div>
page.click('#userinfo button') # 点击id为userinfo内部的标签为button的按钮,使用空格分隔page.click('#userinfo>button') # 点击父元素为id为userinfo的标签为button的按钮,使用>分隔
伪类
并非页面上的属性,而是某种表现形式,可以理解为函数,通过:进行调用,如
page.click('input:nth-child(2)') # 点击具有同一个父节点的第二个inputpage.click('button:not([disabled])') # 点击不具有disabled属性的button按钮
XPATH选择器
由于playwright自定义的扩展选择器使用的是CSS选择器语法,所以建议在使用playwright时主要使用CSS选择器,将XPATH选择器作为补充使用。
Xpath与Iframes互动
iframe1 = page.query_selector('xpath=//iframe[@title="payment"]').content_frame()
time.sleep(5)
iframe1.fill('//*[@id="cardCvc-input"]', '123')
page.navigate("https://antdv.com/components/modal-cn");
page.querySelector("#components-modal-demo-basic .code-box-demo span").click();
page.locator("//div[@id='vcDialogTitle0']|//div[@role='documentcontent']").waitFor();
System.out.println();
文本选择器
文本选择器按照页面显示出的文本定位元素
page.click("text=Log in") # 点击包含文字Log in的元素,不区分大小写且匹配子字符串page.click("text='Log in'") # 文字通过使用引号进行转义,表示只搜索准确文本节点Log in的元素page.click("'Log in'") # 等同于text='Log in'page.click("text=/Log\s*in/i") # javascript正则表达式语法支持page.click("#nav-bar :text('Home')") # text伪类等同于text=*,用于配合CSS选择器一起使用page.click('#nav-bar :text-is("Home")') # text-is伪类等同于text='*',严格匹配文字page.click('#nav-bar :text-matches("reg?ex", "i")') # text=matches伪类等同于text=/reg?ex/i,匹配正则表达式page.click('article:has-text("All products")') # has-text伪类匹配所有包含内部文字的元素,包括body,一般需要配合css选择器一起使用
page.locator("text=社区").click()
page.locator("#main-nav-menu :text('社区')").click()
page.locator('article:has-text("All products")').click()
定位可见元素
:visible伪类匹配可见的元素。例如,input匹配页面上的所有输入框,而input:visible仅匹配可见输入框。这对于区分非常相似但可见性不同的元素很有用。
例如有两个按钮的页面,第一个是不可见的,第二个是可见的:
<button style='display: none'>Invisible</button><button>Visible</button>
page.click("button") # 定位到第一个按钮,因为他是第一个。然后等待按钮变为可见后点击,或超时page.click("button:visible") # 定位到第二个按钮,因为他是可见的
:visible需要小心使用,它有两个主要缺点:
当元素动态更改其可见性时,:visible将基于时序给出不可预测的结果。
:visible可能导致查询变慢,尤其是与方法page.waitForSelector(selector[, options])一起使用时
page.locator("button:visible").click()
page.locator("button >> visible=true").click()
按包含的元素定位
:has 伪类是实验性的,它将定位到包含所给元素定位的元素,如下代码返回包含 <div class="promo">元素的 <article>的元素的文本内容:
page.textContent("article:has(div.promo)")
playwright可以根据页面布局选择元素,与常规CSS结合使用以获得更好的效果,例如 input:right-of(:text("Password"))匹配文本"Password"右侧的输入框
:right-of(inner > selector)- 匹配与内部选择器匹配的任何元素右侧的元素。
:left-of(inner > selector)- 匹配与内部选择器匹配的任何元素左侧的元素。
:above(inner > selector)- 匹配位于与内部选择器匹配的任何元素上方的元素。
:below(inner > selector)- 匹配与内部选择器匹配的任何元素下方的元素。
:near(inner > selector)- 匹配与内部选择器匹配的任何元素附近(50 个 CSS 像素内)的元素
# 在"Username"右侧的输入框中填写'value'.page.fill('input:right-of(:text("Username"))', 'value')# 点击 promo card 附近的按钮.page.click('button:near(.promo-card)')
page.locator("input:right-of(:text('开源项目'))").fill('电子校的故事')
定位第n个元素
有时页面包含许多相似的元素,并且很难选择特定的元素。例如:
<section> <button>Buy</button> </section><article><div> <button>Buy</button> </div></article><div><div> <button>Buy</button> </div></div>
在这种情况下, :nth-match(:text("Buy"), 3)将从上面的片段中选择第三个按钮。请注意,索引是从 1 开始的。
可以使用:nth-match()配合 page.wait_for_selector(selector, **kwargs)等待指定数量的元素出现:
# 等到出现3个可见的按钮page.wait_for_selector(":nth-match(:text('Buy'), 3)")
注意:不同于 :nth-child(),元素不一定是兄弟元素,可以是位于页面上的任何位置
常用
1.text selecter
# Find by text.
page.locator("text=Sign up").click()
2.Css selecter
# Find by CSS.
page.locator("#nav-bar .contact-us-item").click()
3.css and text selecter
page.locator("article:has-text('Playwright')").click()
page.locator("#nav-bar :text('Contact us')").click()
4.css and another selecter
page.locator(".item-description:has(.item-promo-banner)").click()
5.layout selecter
# Fill an input to the right of "Username".
page.locator("input:right-of(:text(\"Username\"))").fill("value")
# Click a button near the promo card.
page.locator("button:near(.promo-card)").click()
# Click the radio input in the list closest to the "Label 3".
page.locator("[type=radio]:left-of(:text(\"Label 3\"))").first.click()
2.Filtering Locators
page.locator("button", has_text="Sign up").click()
page.locator("article", has=page.locator("button.subscribe"))
3.pick n-th application
For Example:
<section> <button>Buy</button> </section>
<article><div> <button>Buy</button> </div></article>
<div><div> <button>Buy</button> </div></div>
# Click the third "Buy" button
page.locator(":nth-match(:text('Buy'), 3)").click()
# Wait until all three buttons are visible
page.locator(":nth-match(:text('Buy'), 3)").wait_for()
import asyncio
from playwright.async_api import async_playwrightasync def main():with async_playwright() as p:browser = p.chromium.launch()# 创建新的隐身浏览器上下文context = await browser.new_context()# 在上下文中创建新页面。page = await context.new_page()await page.goto("https://www.baidu.com")await context.close()
三、页面和框架
浏览器上下文可以有多个页面。页面是指浏览器上下文中的单个选项卡或弹出窗口
四、Selectors
Playwright可以使用CSS选择器,XPath选择器,HTML属性(如)test、id、data-test-id等属性来定位元素。
1、data-test-id= selector
#同步
page.click('data-test-id=foo')
#异步步
await page.click('data-test-id=foo')
2、CSS and XPath selector
#同步
page.click('div')
page.click('//html/body/div')
#异步
await page.click('div')
await page.click('//html/body/div')
3、text 文本selector
page.click('text=Hello')
4、id定位selector
page.fill("id=kw", "csdn")
5、Selector 组合定位
不同的selector可组合使用,用 >>连接。
#单击#free month promo中带有文本“Sign Up”的元素
page.click('#free-month-promo >> text=Sign Up')
五、内置Selector
playwright 推荐的内置定位器:
1. page.get_by_text()通过文本内容定位
2. page.get_by_label()通过关联标签的文本定位表单控件
3. page.get_by_placeholder()按占位符定位输入
4. page.get_by_test_id()根据data-testid属性定位元素(可以配置其他属性)
5. page.get_by_role()通过显式和隐式可访问性属性进行定位
6. page.get_by_alt_text()通过替代文本定位元素,通常是图像
7. page.get_by_title()通过标题属性定位元素
https://playwright.dev/dotnet/docs/writing-tests
https://mp.weixin.qq.com/s?__biz=MzkxMDM1NDQ0OA==&mid=2247498458&idx=2&sn=a93d4ce571ca5d70a779aae9b596f4ae&source=41#wechat_redirect
https://blog.csdn.net/karl41/article/details/119334673
https://article.itxueyuan.com/ZoLrDw
https://betheme.net/dashuju/96613.html?action=onClick
Python开源自动化工具Playwright安装及介绍使用
它支持主流的浏览器,包含:Chrome、Firefox、Safari、Microsoft Edge 等,同时支持以无头模式、有头模式运行,并提供了同步、异步的 API,可以结合 Pytest 测试框架 使用,并且支持浏览器端的自动化脚本录制。
项目地址:https://github.com/microsoft/playwright-python
官网:https://playwright.dev/
2、Playwright安装
Playwright功能强大,但它的安装步骤,非常简单,只需要 2 步:
第 1 步,安装 playwright-python 依赖库 (需要注意的是,playwright库需要依赖Python3.7+以上)
#此处可能是pip/pip3,或者两者皆可
pip3 install playwright
可以在https://pypi.org/project/playwright/查看它的依赖版本信息。
第 2 步,安装主流的浏览器驱动
这样,会将 Chromeium、Firefox、Webkit 浏览器驱动下载到本地
#安装浏览器驱动(安装过程稍微有点慢,请耐心等待)
python3 -m playwright install
如果想查看Playwright支持的功能, 可以直接在命令行输入:
python3 -m playwright help
1)录制脚本
python3 -m playwright codegen --help
python3 -m playwright codegen --target python -o 'mikezhou.py' -b chromium https://www.baidu.com
命令行输入后会自动打开浏览器,然后可以看见在浏览器上的一举一动都会被自动翻译成代码,如下所示:
最后,自动化脚本会自动生成,保存到文件中mikezhou.py, 且上述所有的人工操作,都会被自动转化成代码:
1.cookies
设计思路
对于一些登录比较复杂的网站,具有反爬虫机制,比如手机验证码、滑块验证等,这时可以通过人工手动登录后,保存cookies到指定文件,以后登录就可以通过加载已保存的cookies实现免登陆啦。
1、打开网站登录页面;
2、设置等待时间,进行手工登录;
3、登录后获取并保存cookies。
from playwright.sync_api import sync_playwright
import json
# 先手动登录,保存Cooies到文件。
def saveCookies():
with sync_playwright() as p:
# 显示浏览器,每步操作等待100毫秒
browser = p.firefox.launch(headless=False, slow_mo=100)
context = browser.new_context()
# context.add_init_script(js)
page = context.new_page()
page.goto('https://cq.meituan.com/', timeout=50000) # 设置超时时间为50s
time.sleep(80) # 此处手动登录,然后到个人信息页再获取cookie
cookies = context.cookies()
print(page.title())
browser.close()
f = open('cookies.txt', 'w')
json.dump(cookies, f)
print('已获取cookies')
time.sleep(2)
browser.close()
saveCookies()#执行函数
playwright手动设置cookies和获取cookies的方法
const browser = await chromium.launch({
headless: false
});
const context = await browser.newContext();
const page = await context.newPage();
context.addCookies([
{
"name": ".AspNetCore.Antiforgery.v2CUd5wyqKo",
"domain": "xxxx.com",
"value": "CfDJ8LY97Wcbz7VCv7_x1JiYm96-2kqovbTwK88qSQBNMPKiYPcwfz9WwDsAT72aQUEaQETi3UFYMh9_Kob9nffYFT0A8QqIe7AB96hrgiW0zntQqwBOJASYccsK8ubkZxa2ZN5darwFzORs5ws7s-8BcHA"
"path": "/"
}
])
await page.goto('https://xxxx.com/');
Playwright选择器
CSS选择器
标签
html元素标签,直接写标签名,如
<button value="title"></button> 1
page.click('button') # 点击标签为button的按钮
page.locator("button").click()
ID
元素中的ID属性,在ID前标识#,如
<input id="user"></input>
page.fill('#user', 'username') # 在id=user的输入框中输入username
page.locator('#main-nav-menu [href="/topics"]').click()
Class
元素中的class属性,在class前标识.,如
<input class="btn" type="button"></input>
1
page.click('.btn') # 点击class为btn的按钮
其他属性
元素中除ID和Class的其他属性,使用[attr<=value>]语法,如
<input type="password"></input>
<input type="checkbox" name="vehicle" value="Bike" checked>I have a bike<br>
page.fill('[type=password]', 'password') # 在具有属性type=password的输入框中输入password
page.click('[checked]') # 点击具有属性checked的按钮
page.locator('[href="/topics"]').click()
多种属性同时使用
上述多种选择器可以同时使用,连在一起写即可,如
page.fill('input[type=password]', 'password') # 在具有属性type=password同时标签为input的输入框中输入passwordpage.click('input.btn') # 点击class为btn同时标签为input的按钮
组合选择器
当元素本身的属性不足以唯一定位到我们想要的元素时,可以使用组合选择器,通过元素的父节点或祖先节点来进行唯一定位,如
<div id="user"><button></button></div><div id="userinfo"><button></button></div>
page.click('#userinfo button') # 点击id为userinfo内部的标签为button的按钮,使用空格分隔page.click('#userinfo>button') # 点击父元素为id为userinfo的标签为button的按钮,使用>分隔
伪类
并非页面上的属性,而是某种表现形式,可以理解为函数,通过:进行调用,如
page.click('input:nth-child(2)') # 点击具有同一个父节点的第二个inputpage.click('button:not([disabled])') # 点击不具有disabled属性的button按钮
XPATH选择器
由于playwright自定义的扩展选择器使用的是CSS选择器语法,所以建议在使用playwright时主要使用CSS选择器,将XPATH选择器作为补充使用。
Xpath与Iframes互动
iframe1 = page.query_selector('xpath=//iframe[@title="payment"]').content_frame()
time.sleep(5)
iframe1.fill('//*[@id="cardCvc-input"]', '123')
page.navigate("https://antdv.com/components/modal-cn");
page.querySelector("#components-modal-demo-basic .code-box-demo span").click();
page.locator("//div[@id='vcDialogTitle0']|//div[@role='documentcontent']").waitFor();
System.out.println();
文本选择器
文本选择器按照页面显示出的文本定位元素
page.click("text=Log in") # 点击包含文字Log in的元素,不区分大小写且匹配子字符串page.click("text='Log in'") # 文字通过使用引号进行转义,表示只搜索准确文本节点Log in的元素page.click("'Log in'") # 等同于text='Log in'page.click("text=/Log\s*in/i") # javascript正则表达式语法支持page.click("#nav-bar :text('Home')") # text伪类等同于text=*,用于配合CSS选择器一起使用page.click('#nav-bar :text-is("Home")') # text-is伪类等同于text='*',严格匹配文字page.click('#nav-bar :text-matches("reg?ex", "i")') # text=matches伪类等同于text=/reg?ex/i,匹配正则表达式page.click('article:has-text("All products")') # has-text伪类匹配所有包含内部文字的元素,包括body,一般需要配合css选择器一起使用
page.locator("text=社区").click()
page.locator("#main-nav-menu :text('社区')").click()
page.locator('article:has-text("All products")').click()
定位可见元素
:visible伪类匹配可见的元素。例如,input匹配页面上的所有输入框,而input:visible仅匹配可见输入框。这对于区分非常相似但可见性不同的元素很有用。
例如有两个按钮的页面,第一个是不可见的,第二个是可见的:
<button style='display: none'>Invisible</button><button>Visible</button>
page.click("button") # 定位到第一个按钮,因为他是第一个。然后等待按钮变为可见后点击,或超时page.click("button:visible") # 定位到第二个按钮,因为他是可见的
:visible需要小心使用,它有两个主要缺点:
当元素动态更改其可见性时,:visible将基于时序给出不可预测的结果。
:visible可能导致查询变慢,尤其是与方法page.waitForSelector(selector[, options])一起使用时
page.locator("button:visible").click()
page.locator("button >> visible=true").click()
按包含的元素定位
:has 伪类是实验性的,它将定位到包含所给元素定位的元素,如下代码返回包含 <div class="promo">元素的 <article>的元素的文本内容:
page.textContent("article:has(div.promo)")
playwright可以根据页面布局选择元素,与常规CSS结合使用以获得更好的效果,例如 input:right-of(:text("Password"))匹配文本"Password"右侧的输入框
:right-of(inner > selector)- 匹配与内部选择器匹配的任何元素右侧的元素。
:left-of(inner > selector)- 匹配与内部选择器匹配的任何元素左侧的元素。
:above(inner > selector)- 匹配位于与内部选择器匹配的任何元素上方的元素。
:below(inner > selector)- 匹配与内部选择器匹配的任何元素下方的元素。
:near(inner > selector)- 匹配与内部选择器匹配的任何元素附近(50 个 CSS 像素内)的元素
# 在"Username"右侧的输入框中填写'value'.page.fill('input:right-of(:text("Username"))', 'value')# 点击 promo card 附近的按钮.page.click('button:near(.promo-card)')
page.locator("input:right-of(:text('开源项目'))").fill('电子校的故事')
定位第n个元素
有时页面包含许多相似的元素,并且很难选择特定的元素。例如:
<section> <button>Buy</button> </section><article><div> <button>Buy</button> </div></article><div><div> <button>Buy</button> </div></div>
在这种情况下, :nth-match(:text("Buy"), 3)将从上面的片段中选择第三个按钮。请注意,索引是从 1 开始的。
可以使用:nth-match()配合 page.wait_for_selector(selector, **kwargs)等待指定数量的元素出现:
# 等到出现3个可见的按钮page.wait_for_selector(":nth-match(:text('Buy'), 3)")
注意:不同于 :nth-child(),元素不一定是兄弟元素,可以是位于页面上的任何位置
常用
1.text selecter
# Find by text.
page.locator("text=Sign up").click()
2.Css selecter
# Find by CSS.
page.locator("#nav-bar .contact-us-item").click()
3.css and text selecter
page.locator("article:has-text('Playwright')").click()
page.locator("#nav-bar :text('Contact us')").click()
4.css and another selecter
page.locator(".item-description:has(.item-promo-banner)").click()
5.layout selecter
# Fill an input to the right of "Username".
page.locator("input:right-of(:text(\"Username\"))").fill("value")
# Click a button near the promo card.
page.locator("button:near(.promo-card)").click()
# Click the radio input in the list closest to the "Label 3".
page.locator("[type=radio]:left-of(:text(\"Label 3\"))").first.click()
2.Filtering Locators
page.locator("button", has_text="Sign up").click()
page.locator("article", has=page.locator("button.subscribe"))
3.pick n-th application
For Example:
<section> <button>Buy</button> </section>
<article><div> <button>Buy</button> </div></article>
<div><div> <button>Buy</button> </div></div>
# Click the third "Buy" button
page.locator(":nth-match(:text('Buy'), 3)").click()
# Wait until all three buttons are visible
page.locator(":nth-match(:text('Buy'), 3)").wait_for()
import asyncio
from playwright.async_api import async_playwrightasync def main():with async_playwright() as p:browser = p.chromium.launch()# 创建新的隐身浏览器上下文context = await browser.new_context()# 在上下文中创建新页面。page = await context.new_page()await page.goto("https://www.baidu.com")await context.close()
三、页面和框架
浏览器上下文可以有多个页面。页面是指浏览器上下文中的单个选项卡或弹出窗口
四、Selectors
Playwright可以使用CSS选择器,XPath选择器,HTML属性(如)test、id、data-test-id等属性来定位元素。
1、data-test-id= selector
#同步
page.click('data-test-id=foo')
#异步步
await page.click('data-test-id=foo')
2、CSS and XPath selector
#同步
page.click('div')
page.click('//html/body/div')
#异步
await page.click('div')
await page.click('//html/body/div')
3、text 文本selector
page.click('text=Hello')
4、id定位selector
page.fill("id=kw", "csdn")
5、Selector 组合定位
不同的selector可组合使用,用 >>连接。
#单击#free month promo中带有文本“Sign Up”的元素
page.click('#free-month-promo >> text=Sign Up')
五、内置Selector
playwright 推荐的内置定位器:
1. page.get_by_text()通过文本内容定位
2. page.get_by_label()通过关联标签的文本定位表单控件
3. page.get_by_placeholder()按占位符定位输入
4. page.get_by_test_id()根据data-testid属性定位元素(可以配置其他属性)
5. page.get_by_role()通过显式和隐式可访问性属性进行定位
6. page.get_by_alt_text()通过替代文本定位元素,通常是图像
7. page.get_by_title()通过标题属性定位元素