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()通过标题属性定位元素







posted @ 2023-04-25 08:11  桃花雪  阅读(382)  评论(0编辑  收藏  举报