playWright 入门
安装命令
python环境终端
terminal> pip install playwright terminal> playwright install terminal> pip install pytest-playwright
使用
自带工具
- playwright codegen :浏览器相关操作
- playwright inspector :记录用户在 codegen 打开的浏览器的操作流程,生成相应的python代码
# 打开终端 # 打开百度 terminal> playwright codegen www.baidu.com # 打开百度,窗口设置为800X600 terminal> playwright codegen --viewport-size=800,600 www.baidu.com # 模拟iPhone13 打开百度 terminal> playwright codegen --device="iPhone 13" www.baidu.com # 浏览器打开百度,进行登录,保存登录信息 terminal> playwright codegen --save-storage=auth.json www.baidu.com # 浏览器打开百度,加载上次保存的登录信息,无需再次登录 terminal> playwright codegen --load-storage=auth.json www.baidu.com # 模拟地理位置、语言和时区 terminal> playwright open --timezone="Europe/Rome" --geolocation="41.890221,12.492348" --lang="it-IT" maps.google.com
基本使用
1,入门第一个程序
import time
from playwright.sync_api import Playwright, sync_playwright, expect
def run(playwright: Playwright) -> None:
browser = playwright.chromium.launch(headless=False)
# 如果headless=False,则浏览器会以普通模式打开,我们可以直接看到浏览器界面和操作。
# 如果headless=True,则浏览器会以无头模式启动,我们看不到浏览器界面,但可以通过Playwright控制和自动化浏览器。
context = browser.new_context()
# 在浏览器中创建了一个新的上下文。上下文相当于一个隐身的浏览器实例,每个上下文都拥有自己的本地存储、Cookie和权限等
page = context.new_page()
# 在上下文context中打开一个新的页面page。
page.goto("https://www.baidu.com/")
# ---------------------
time.sleep(3)
context.close()
browser.close()
with sync_playwright() as playwright:
run(playwright)
2,浏览器操作
from playwright.sync_api import Playwright, sync_playwright, expect
with sync_playwright() as pw:
browser = pw.chromium.launch(headless=False,
args=["--start-maximized"], # 最大化
slow_mo=3000 # 单位毫秒,这里表示在每次操作之间都将等待3秒。
)
page = browser.new_page(viewport={"width": 1920, "height": 1080}) # 窗口大小1920x1080
page.goto("https://www.zhihu.com")
page.get_by_text("开通机构号").click() # 寻找“开通机构号"文本,点击
page.go_back() # 后退
page.go_forward() # 前进
page.reload() # 刷新
browser.close() # 关闭
playwright.chromium.launch()方法参数说明
- headless:是否以无头模式启动浏览器,默认为True - slow_mo:设置操作之间的延迟时间,单位ms,默认为0 - devtools:是否打开开发者工具,默认为False - args:传递给浏览器的命令行参数,以列表形式 - proxy:设置浏览器的代理,详情见下文 - timeout:最大启动时间,默认为30000ms - ignore_https_errors:是否忽略HTTPS错误,默认为False - firefox_user_prefs: Firefox浏览器设置,Chrome浏览器无效 - viewport:设置默认页面视口大小 - env:设置环境变量 - ignore_default_args:是否忽略Chrome浏览器的默认参数 - user_data_dir:设置浏览器运行使用的用户数据目录 这些参数的具体作用如下: - headless:以无头模式启动更快,用于无界面自动化;非无头模式可视化自动化过程 - slow_mo:设置延迟便于学习与调试,发布时置0 - devtools:打开开发者工具进行手动调试 - args:传入其他命令行参数,如 "--start-maximized" 最大化窗口 - proxy:设置网络代理,形如 {"server":"ip:port"} - timeout:设置启动超时时间,避免浏览器启动失败卡住自动化进程 - ignore_https_errors:忽略证书错误访问https站点 - viewport:设置页面默认视口大小,如 {"width": 1024, "height": 768} - env:传入环境变量,如 {"foo": "bar"} - user_data_dir:设置用户数据目录,用于evals隔离浏览器数据
3,元素定位
Xpath
定位首先可通过浏览器调试工具预先检验xpath是否正确
打开调试页面,在
Element
页面打开consol
窗口在
consol
窗口输入$x('你的xpath路径')
进行调试
XPath
基本语法如下:
节点选择-
//div
:选择所有div元素节点
/div
:选择根元素下的div元素
div/p
:选择div元素下的p子元素
//div/p
:选择任何div下的p子元素谓词
//div[@id]
:选择所有具有id属性的div元素
//div[@id='hello']
:选择所有id属性值为hello的div元素
//div[last()]
:选择最后一个div元素
//div[position()<3]
:选择前两个div元素
//div[price>35]
:选择price属性值大于35的div元素轴
//div/child::p
:选择div元素的p子元素
//div/parent::*
:选择div元素的父元素
//div/ancestor::*
:选择div的祖先元素
//div/following-sibling::*
:选择div元素之后的同级元素
//div/preceding-sibling::*
:选择div元素之前的同级元素运算符
//div + p
:选择div元素之后的第一个p元素
//div | //p
:选择所有div和p元素
//div/p | //span
:选择所有div/p元素和span元素属性值选择
//div[@id='hello' and @class='world']
:选择id为hello且class为world的div元素
//div[@id='hello' or @class='world']
:选择id为hello或class为world的div元素通配符
//*
:选择所有元素
//div/*
: 选择div元素的所有子元素1)基本定位方法
# 单一属性定位 page.locator('xpath') # 多属性定位 page.locator('xpath1 and xpath2') # xpath可定位到多个结果,这里返回的是列表类型 page.locator('xpath').all() # 寻找带有“同意”文本的按钮,返回列表类型 agree_text = "同意" agree_buttons = page.query_selector_all(f"button:has-text('{agree_text}')")
2)CSS选择器
# 选择class为date-day的div标签,并且排除包含date-nocurrent、date-disabled的div标签 page.locator("div.date-day:not(.date-nocurrent):not(.date-disabled)") # 也可以带上路径 page.locator('div.date-month > div > div.date-day:not(.date-nocurrent):not(.date-disabled)')
3)xpath选择器
# 选择class为date-day的div标签,并且排除包含date-nocurrent、date-disabled的div标签 # 绝对路径 page.locator('xpath=/html/body/div[contains(@class, "date-day") and not(contains(@class, "date-disabled"))]')
特别注意,CSS选择器 和 xpath选择器 语法不能混用
4,page.on()监听,抓取数据
举个例子:通过 百度地图 搜索地址,获取request接口链接,再获取接口返回数据
from playwright.sync_api import sync_playwright
# 定义一个全局变量
respData = []
def on_response(response):
try:
# 筛选请求,并判断状态
if 'da_src=searchBox.button' in response.url and response.status == 200:
json_data = response.json()["content"][0]["admin_info"]
global respData
respData.append(json_data)
except Exception as e:
print(e)
def baiduMapSearch():
try:
with sync_playwright() as pw:
browser = pw.chromium.launch(headless=False)
page = browser.new_page()
# page.on()函数用于为某个事件添加监听器回调函数。
# 这里在监听 response 事件,如果捕获到response事件则调用 on_response 函数
page.on('response', on_response)
page.goto("https://map.baidu.com/")
page.locator('//*[@id="TANGRAM__PSP_37__closeBtn"]').click()
search_text = page.locator('//*[@id="sole-input"]')
search_button = page.locator('//*[@id="search-button"]')
except Exception as e:
print(e)
如果需要传递参数,可以使用以下方法
from functools import partial
def handle_request(request, param1, param2):
pass
page.on('request', partial(handle_request, param1=value1, param2=value2))
page.on()函数用于为某个事件添加监听器回调函数。语法为:
page.on(event, listener)
- event:字符串,表示要监听的事件名称,如’response’、‘request’、'dialog’等。
- listener:回调函数,当事件触发时会被调用。例如:
# 当页面有response时调用on_response函数 page.on('response', on_response) # 定义回调函数 def on_response(response): print(response.url)
在 Python 的 Playwright 中,
page.on()
方法可以监听以下事件:
close
: 当页面关闭时触发。console
: 当页面中有新的控制台消息时触发,包括日志、警告和错误消息。crash
: 当页面崩溃时触发。dialog
: 当页面出现对话框时触发,例如alert
,confirm
,prompt
等。domcontentloaded
: 当页面的 DOMContentLoaded 事件触发时触发。download
: 当页面下载文件时触发。filechooser
: 当页面中有文件选择器时触发。frameattached
: 当页面中有新的子 frame 时触发。framedetached
: 当页面中的子 frame 被移除时触发。framenavigated
: 当页面的子 frame 导航到新的 URL 时触发。load
: 当页面完全加载时触发。pageerror
: 当页面中有 JavaScript 错误时触发。request
: 当页面发出新的网络请求时触发。requestfailed
: 当页面中的请求失败时触发。requestfinished
: 当页面中的请求完成时触发。response
: 当页面接收到新的网络响应时触发。workercreated
: 当页面中有新的 Web Worker 时触发。workerdestroyed
: 当页面中的 Web Worker 被销毁时触发。你可以通过在
page.on()
方法中传递相应的事件名称来监听这些事件。当事件被触发时,回调函数将被调用。回调函数的参数和返回值取决于事件类型。可以在 Playwright 的官方文档中找到关于这些事件的详细信息。