playwright-python 元素定位、frame处理(一)
阅读原文时间:2023年07月10日阅读:2

浏览器、Browser contexts、frame

Playwright 可以同时启动多个浏览器(chromium、Firefox、webkit),每个浏览器可以启动多个page(在Playwright上称作Browser contexts

浏览器

启动浏览器代码样例:

from playwright import sync_playwright

with sync_playwright() as p:
    # 可以选择chromium、firefox和webkit
    browser_type = p.chromium
    # 运行chrome浏览器,executablePath指定本地chrome安装路径
    # browser = browser_type.launch(headless=False,slowMo=50,executablePath=r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe")
    browser = browser_type.launch(headless=False)
    page = browser.newPage()
    page.goto('https://www.baidu.com/')
    page.screenshot(path=f'example-{browser_type.name}.png')
    browser.close()
Browser contexts

同一个浏览器启动多个page,可以模拟多页面的场景:

from playwright import sync_playwright

with sync_playwright() as p:
    browser_type = p.chromium
    browser = browser_type.launch(headless=False)
    context = browser.newContext()
    page1 = context.newPage()
    page1.goto('https://mail.163.com/')
    page1.screenshot(path=f'page1-{browser_type.name}.png')
    page2 = context.newPage()
    page2.goto("https://www.baidu.com/")
    page2.screenshot(path=f'page2-{browser_type.name}.png')
    context.close()
    browser.close()

Browser contexts还可以模拟移动设备:

from playwright import sync_playwright

with sync_playwright() as p:
    browser_type = p.chromium
    iphone_11 = p.devices['iPhone 11 Pro']
    browser = browser_type.launch(headless=False)
    context = browser.newContext(**iphone_11, permissions=['geolocation'], colorScheme='dark', locale='zh-CN')
    page = context.newPage()
    page.goto('https://mail.163.com/')
    page.screenshot(path=f'page2-{browser_type.name}.png')
    context.close()
    browser.close()
frame

处理frame,查找frame有三种方法:

  1. framename属性

  2. frameURL

  3. 通过其他的任何的selector

    from playwright import sync_playwright

    with sync_playwright() as p:
    browser_type = p.chromium
    browser = browser_type.launch(headless=False)
    page = browser.newPage()
    page.goto('https://mail.163.com/')
    # 通过selector、name、URL
    login_frame = page.querySelector("[id^='x-URS-iframe']").contentFrame()
    # login_frame = page.querySelector("#loginDiv>iframe").contentFrame()
    # login_frame2 = page.frame("name").contentFrame()
    # login_frame3 = page.frame("URL").contentFrame()
    # 查看所有的frames
    print(page.frames)
    login_frame.fill("input[name='email']", "test123")
    login_frame.fill("input[name='password']", "1234")
    login_frame.click("#dologin")
    page.screenshot(path=f'example-{browser_type.name}.png')
    browser.close()

元素选择器(元素查找)

语法

Playwright可以使用CSS选择器XPath选择器HTML属性(如id、data-test-id,甚至文本内容)来搜索元素。只需直接使用即可,可以自动探测

简写
  1. 选择器以// 或者..开头,则会默认为是xpath=selector

    • 例子:page.click('//html') 可转换为 page.click('xpath=//html')
  2. 选择器开始和结束以引号("或者'),则默认为text=selector

    • 例子:page.click(' "foo" ') 可转换为 page.click('text="foo"')
  3. 其他的默认为是css=selector

    • 例子:page.click('div') 可转换为 page.click('css=div')
链式选择器

选择器可以与>>组合使用,例如selector1 >> selector2 >> selectors3。当选择器被链接时,下一个选择器会相对于前一个选择器的结果进行查询。

例如:

page.querySelector('css=article >> css=.bar > .baz >> css=span[attr=value]')

等同于:

page.querySelector('article').querySelector('.bar > .baz').querySelector('span[attr=value]')

css=article >> text=Hello查找文本为Hello的 article 元素;*css=article >> text=Hello查找包含文本Hello的 article 元素

最佳实践

以下只是写出了部分用法,详情参考

  • 使用data-test-id

    page.click("data-test-id=login")
  • CSS 和 XPath

    page.click('div')
    page.click('//html/body/div')
    # 明确指定类型
    page.click('css=div')
    page.click('xpath=//html/body/div')
    # 点击#free-month-promo元素内文本为“Sign Up”的元素
    page.click('#free-month-promo >> text=Sign Up')
    
    page.fill('css=[placeholder="Search GitHub"]')
    page.fill('[placeholder="Search GitHub"]') # 简写
  • 通过文本子字符串查找

    page.click('text="Login"')
    page.click('"Login"'); # 简写
  • 获取某元素内的所有文本

    print(page.evalOnSelector('.headerLogo', """e => e.textContent"""))
    print(page.querySelector('.headerLogo').textContent())
  • CSS 扩展 : visible

    # 点击第一个button
    page.click('button')
    # 点击第一个可视的button,如果有其他不可视的,则会忽略他们
    page.click('button:visible')
  • CSS扩展: text

    • :text("substring")当元素的文本在某处包含"substring"时进行匹配。匹配是不区分大小写的。匹配还对空格进行规范化,例如,它将多个空格转换为一个空格,换行并忽略开头和结尾的空格

    • :text-is("string")当元素的文本等于"string"时进行匹配。匹配不区分大小写,并且对空格规格化

    • button:text("Sign in")文本选择器可以与常规CSS相结合

    • :text-matches("[+-]?\\d+")根据正则表达式匹配文本。注意,像反斜杠\,引号",方括号[]和更多的特殊字符应该被转义。

    • :text-matches("value", "i")使用指定的标记匹配正则表达式的文本

      page.click('button:text("Sign in")')
      page.querySelector(':text("163网易邮箱")').textContent()

参考