Playwright 入门详细教程

playwright的python文档

安装

pip install playwright

# 安装驱动, 支持的浏览器:cr, chromium, ff, firefox, wk 和 webkit
playwright install

控制台启动录制

playwright codegen [options] [url]
  • -o, --output :保存生成脚本
  • –target :生成的脚本语言,可以设置javascript, test, python, python-async和csharp,默认为python
  • -b, --browser :要使用的浏览器,可以选择cr, chromium, ff, firefox, wk和webkit,默认chromium。
  • –channel :chromium版本,比如chrome, chrome-beta, msedge-dev等
  • –color-scheme :模拟器的颜色主题,可选择light 或者 dark样式
  • –device :模拟的设备
  • –save-storage :保存上下文状态,用于保存cookies 和localStorage,可用它来实现重用。例如playwright codegen --save-storage=auth.json
  • –load-storage :加载–save-storage 保存的数据,重用认证数据。
  • –proxy-server :指定代理服务器
  • –timezone
  • –geolocation :指定地理位置坐标
  • –lang :指定语言/地区,比如中国大陆:zh-CN
  • –timeout :超时时间,定位毫秒,默认10000ms
  • –user-agent :用户代理
  • –viewport-size :浏览器窗口大小
  • -h, --help :查看帮助信息

例如:

playwright codegen -o test_playwright.py --target python  -b chromium --device="iPhone 12 Pro" https://www.baidu.com/

playwright open https://www.baidu.com/ # 默认使用Chromium打开
playwright wk https://www.baidu.com/ # 使用WebKit打开
playwright open --device="iPhone 12 Pro" https://www.baidu.com/ # 使用iPhone 12 Pro模拟器打开

基本用法

常见配置参数

headless,slow_mo,viewport,locale,timezone,color_scheme,geolocation,user_agent, timeout, proxy

同步模式

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
	# 创建一个浏览器实例; headless:是否无头;slow_mo放慢执行速度
	
	# pixel_2 = playwright.devices['Pixel 2']  # Pixel 2 一款安卓手机
	proxy_ip = {
            'server': 'http://',
            'username': '',
            'password': '',
        }
    browser = p.chromium.launch(headless=False, slow_mo=100, proxy=proxy_ip)
	context = browser.new_context(
            viewport={'width': 1800, 'height': 800},	# 窗口大小
            locale='zh-CN',  #语言zh-CN/en-EN
            timezone='Europe/Rome',   #时区
            color_scheme='dark',	# 颜色
            geolocation={"longitude": 48.858455, "latitude": 2.294474} # 地理位置
            user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36', # 浏览器,
            timeout=10000, # 超时
            # **pixel_2,
        )
	
    # 创建两个浏览器上下文
    page = browser.new_page()
    page.goto('http://www.baidu.com')
    print(page.title)
    browser.close()

异步模式

import asyncio
from playwright.async_api import async_playwright
async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=False)
        page = await browser.new_page()
        await page.goto("http://www.baidu.com")
        print(await page.title())
        await browser.close()

asyncio.run(main())

防止WebDriver 被检测

js = """
Object.defineProperties(navigator,{webdriver:{get:()=>undefined}};
"""
page.add_init_script(js)

或者
page.add_init_script("""Object.defineProperties(navigator, {webdriver:{get:()=>undefined}});""")

获取源码,文本,属性

获取源码: .content()
page.wait_for_load_state('networkidle')
html = page.content()
获取文本: .text_content()
# ul->li下
brand = element.query_selector('text=品牌:').text_content()

name = ele_items.query_selector('section > div._3KXtu._3jY37 > a').text_content()
获取属性: .get_attribute()
# ul->li下
 link = element.query_selector('h5 a').get_attribute('href')

wait_for_load_state

"commit ": 接收到网络响应且文档开始加载时(仅显示了页面默认窗口视图下的元素)
"domcontentloaded": 认为在 DOMContentLoaded 事件完成时(显示了完整页面)
"load": 在 load 事件完成时操作完成(含了所有图片资源)
"networkidle": 至少 500 毫秒内没有网络连接时操作完成

页面加载的整个状态变化
Commit -> DOMContentLoaded -> load -> networkidle

监听 response 事件:page.on()

from playwright.sync_api import sync_playwright
 
def on_response(response):
    if '/api/movie/' in response.url and response.status == 200:
        print(response.json())
        print(f'Statue {response.status}:{response.url}')
 
with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    # Page 就是单独的一个浏览器 tab 标签
    page = browser.new_page()
    page.on('response', on_response)
    # page.on('response', lambda response: on_response(response, product_data, id))
    page.goto('https://spa6.scrape.center/')
    page.wait_for_load_state('networkidle')
    browser.close()

# 监听弹窗
with page.expect_popup() as popup:
	page.evaluate('window.open()')
popup.value.goto('http://www.baidu.com')
# 监听请求
with page.expect_request('**/*login*.png') as first:
	page.goto('http://www.baidu.com')
print(first.value.url)

传参监听

 page.on('response', lambda response: on_response(response, id))
 for (url, id) in urls:
 	pass

滚动

下拉滚动条
page.evaluate("var q=document.documentElement.scrollTop=15000")
鼠标滚动
page.mouse.wheel(0,7000)

截图

 with sync_playwright() as p:
        browser = p.chromium.launch(headless=False, slow_mo=50)
        page = browser.new_page()
        page.goto("http://www.baidu.com")
        page.screenshot(path="example.png")
        browser.close()

获取cookie

browser = playwright.chromium.launch(headless=False)
context = browser.new_context()

cookies = context.storage_state()
cookie = '; '.join([f'{key["name"]}={key["value"]}' for key in cookies['cookies']])

CSS,xpath选择器

t伪类选择器
has-text():检测包含(返回找到的所有元素)
text():检测等于(返回第一个找到的元素)

# 选择文本是 Log in 的节点,并点击
page.click("text=Log in",timeout=5000)
page.click("text=你好,请登录")

page.locator(':has-text("All products")').click() 

page.locator("#nav-bar :text('Contact us')").click()
page.locator('[data-test=login-button]').click()
page.locator("[aria-label='Sign in']").click()

# 选择 id 为 nav-bar 子孙节点 class 属性值为 contact-us-item,并点击
page.click("#nav-bar .contact-us-item")
 
# 选择文本中包含 Playwright 的 article 节点
page.click("article:has-text('Playwright')")
 
# 选择 id 为 nav-bar 节点中文本值等于 Contact us 的节点
page.click("#nav-bar :text('Contact us')")
 
# 选择 class 为 item-description 的节点,且该节点还要包含 class 为 item-promo-banner 的子节点
page.click(".item-description:has(.item-promo-banner)")
 
# 择的就是一个 input 节点,并且该 input 节点要位于文本值为 Username 的节点的右侧
page.click("input:right-of(:text('Username'))")

# xpath
page.click("xpath=//button")

get_by_xxx定位器

page.get_by_text(文本,**kwargs)按文本内容定位
page.get_by_role(角色,**kwargs)按角色属性

page.get_by_label(文本,**kwargs)通过关联标签的文本查找表单控件
page.get_by_test_id(test_id)根据元素的属性定位元素(可以配置其他属性)
page.get_by_placeholder(文本,**kwargs)按占位符查找输入

通过其文本替代来定位元素,通常是图像。
page.get_by_title(文本,**kwargs)按标题定位元素。

page.get_by_label("Password").fill("secret-password")

page.get_by_role("option", name="全部企业").click()
page.get_by_role("button", name="Sign in").click()

# 关闭详情弹窗
page.frame_locator("internal:attr=[title=\"详情页\"i]").locator(
                "#enterprise-details-close").click()

# 文本内容
page.get_by_text(str(select_text)).click()

# 正则匹配定位
page.get_by_role("tab", name=re.compile("风险信息", re.IGNORECASE)).click()

正则定位

循环遍历ul: query_selector_all()

uls = page.query_selector_all('//*[@id="YZhV9-anchor"]//table[@class="ant-table-fixed"]/tbody/tr')
for ele_items in uls:
	title = ele_items.query_selector('section > div._3KXtu._3jY37 > a').text_content()

同级第几个:.nth(2)

点击最后一个按钮
page.click("button >> nth=-1")

page.get_by_placeholder("请输入手机号码").nth(1).click()

文本输入:.fill()

# 标签定位输入
page.locator('text=First Name').fill('Peter')

page.get_by_placeholder("请输入手机号码").nth(1).fill('12345678901')

定位器过滤器:filter

page.locator("a").filter(has_text="密码登录").click()

刷新,前进,后退

page.reload(**kwargs) # 刷新
page.go_back(**kwargs)  # 后退
page.go_forward(**kwargs)  # 前进

等待

# 等待直到title元素被加载完全
page.locator("title").wait_for()   

# 会自动等待按钮加载好再执行点击
page.locator("button", has_text="sign up").click() 

# Playwright 会等待 #search 元素出现在 DOM 中
page.fill('#search', 'query')

# Playwright 会等待元素停止动画并接受点击
page.click('#search')

# 等待 #search 出现在 DOM 中
page.wait_for_selector('#search', state='attached')
# 等待 #promo 可见, 例如具有 `visibility:visible` 
page.wait_for_selector('#promo')

# 等待 #details 变得不可见, 例如通过 `display:none`.
page.wait_for_selector('#details', state='hidden')

# 等待 #promo 从 DOM 中移除
page.wait_for_selector('#promo', state='detached')


# 随机等待
page.wait_for_timeout(random.uniform(2500, 4500))

点击

  • 左键点击:page.click(“id=su”)
  • 点击元素左上角:page.click(‘id=su’, position={‘x’: 0, ‘y’: 0})
  • Shift + click:page.click(“id=su”, modifiers=[‘Shift’])
  • 强制点击:page.click(“id=su”, force=True)
  • 右键点击:page.click(“id=su”, button=‘right’)
  • 双击:page.dblclick(“id=su”)
  • 悬停在元素上:page.hover(‘id=su’)

模拟键盘输入

page.press("id=kw", 'Control+A'):Control+A
page.press('id=kw', 'Enter'):点击回车

# 一个字符一个字符的输入
page.type("id=kw", "playwright", delay=100): 每个字符延迟100ms输入

参考:
https://huaweicloud.csdn.net/63802f5edacf622b8df864ec.html#devmenu22
https://blog.csdn.net/u010698107/article/details/121070336

  • 3
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值