专栏文章 playwright 之定位篇 - 下

莫离 · 2022年09月21日 · 最后由 行吧,就这样吧 回复于 2022年10月14日 · 17575 次阅读

文本框不同类型输入

# 文本输入
page.locator('#name').fill('Peter')

# 日期输入
page.locator('#date').fill('2020-02-02')

# 时间输入
page.locator('#time').fill('13:15')

# 本地时间输入
page.locator('#local').fill('2020-03-02T05:15')

# 通过label输入,注意只能针对特定情况使用
page.locator('text=First Name').fill('Peter')

标准 select 选择选择

# 通过值
page.locator('select#colors').select_option('blue')

# 通过label
page.locator('select#colors').select_option(label='Blue')

# 多选
page.locator('select#colors').select_option(['red', 'green', 'blue'])

另:如果是 tagname 不是 select 的选择框,可以通过多次点击的方式选择

文件上传

# 选择一个文件
page.locator('input#upload').set_input_files('myfile.pdf')

# 选择多个文件
page.locator('input#upload').set_input_files(['file1.txt', 'file2.txt'])

# 移除全部已选的文件
page.locator('input#upload').set_input_files([])

# 从内存上传缓冲区
page.locator("input#upload").set_input_files(
    files=[
        {"name": "test.txt", "mimeType": "text/plain", "buffer": b"this is a test"}
    ],
)

dialog 弹窗

#弹窗中确认
page.on("dialog", lambda dialog: dialog.accept())
page.locator("button").click()
#弹窗中取消
page.on("dialog", lambda dialog: dialog.dismiss())
page.locator("button").click()

iframe 内元素操作

#首选定位iframe需要操作的元素~然后操作不是selenium得切入切出
username = page.frame_locator('.frame-class').locator('#username-input')
username.fill('John')

获取 table 中数据

#返回table中第一个tr,返回格式是list
rows = page.locator("table tr")
#获取全本内容
texts = rows.all_text_contents()

连接定位 用于层级定位

css=article >> css=.bar > .baz >> css=span[attr=value]
# 等同于
document
  .querySelector('article')
  .querySelector('.bar > .baz')
  .querySelector('span[attr=value]')

通过 nth 下标定位

# 点击第一个按钮,从0开始
page.locator("button >> nth=0").click()
# 或者
page.locator("button").first.click()
# 点击最后一个难就
page.locator("button >> nth=-1").click()

截屏

# 浏览器截屏
page.screenshot(path="screenshot.png")
#截全屏
page.screenshot(path="screenshot.png", full_page=True)
#截元素,验证码OCR识别可用
page.locator(".header").screenshot(path="screenshot.png")

等待

自动等待解决了一部分,具体见下表

Action Attached Visible Stable Receives Events Enabled Editable
check Yes Yes Yes Yes Yes -
click Yes Yes Yes Yes Yes -
dblclick Yes Yes Yes Yes Yes -
setChecked Yes Yes Yes Yes Yes -
tap Yes Yes Yes Yes Yes -
uncheck Yes Yes Yes Yes Yes -
hover Yes Yes Yes Yes - -
scrollIntoViewIfNeeded Yes - Yes - - -
screenshot Yes Yes Yes - - -
#强制等待同time.sleep(3)
page.wait_for_timeout(3000)
#等待页面加载完成
page.wait_for_load_state() 
方法支持3种参数 load domcontentloaded  networkidle
共收到 10 条回复 时间 点赞

playwright 有像 selenium grid 那样的分布式解决方案吗?之前找资料找了好久,最接近的一个案例是改源码自己去写 socket,替换掉中间 python 跟 node.js 交互的 socket 来达成控制远程设备浏览器的目标,但是这样做成本太高了😂

比较常用的,还有比较好用的定位方式是根据方位来:

page.click("button:right-of(#search)") # 右边
page.click("button:left-of(#search)") # 左边
page.click("button:above(#search)") # 上边
page.click("button:below(#search)") # 下边
page.click("button:near(#search, 50)") # 50px 之内的元素

refrain 回复

暂时还没有。我当前是将 case 分组,多进程来实现提速。

大佬啥时候解读下 vue 定位啊

refrain 回复

现在只有 pytest --numprocesses auto 这个,可以考虑下 celery。。。 其实 mq 不用什么高级特性也没那么难

根据官网的描述
1、VUE 这个选择器只能通过 vue devtools 使用
2、vue devtools 呢 又要打包的时候配。。
3、所以估计可用性够呛,我就没弄。因为我们家 web 开发是不让我拉他们代码然后改打包配置的,改错了就是我改配置文件打包然后他打我。

有几个问题...

切换窗口的方法是什么,selenium 是 switch_to.window()
连接已打开的浏览器有什么方法

refrain 回复

https://playwright.dev/python/docs/selenium-grid
突然看到了这个~ 没自己试。。。看起来是可以直接用 slenium-grid 的

from playwright.sync_api import Playwright, sync_playwright

def run(playwright: Playwright) -> None:
    browser = playwright.chromium.launch(headless=False)
    context = browser.new_context()
    page = context.new_page()
    page.goto("https://www.baidu.com/")
    #点击新闻打开新窗口
    with page.expect_popup() as new_page_info:
        page.locator("#s-top-left >> text=新闻").click()
    new_page = new_page_info.value
    #在新窗口中操作
    new_page.locator("text=百度一下 帮助 >> input[name=\"word\"]").fill("123")
    page.wait_for_timeout(3000)
    print(new_page.title())
    context.close()
    browser.close()
with sync_playwright() as playwright:
    run(playwright)

亲测可用! 切换窗口

连接已打开的浏览器有什么方法 暂时没找到。。

莫离 回复

芜湖~ 收到,感谢

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册