Scrapy与分布式开发(2.5):自动化工具playwright
Python Playwright 模块详细讲解
一、简介
Playwright 是一个无头浏览器测试库,它允许你使用 Python 脚本控制浏览器自动化,执行各种浏览器操作,如点击、填写表单、导航至页面等。Playwright 支持 Chromium (包括 Chrome 和 Edge)、Firefox 和 Webkit (包括 Safari) 这三种主流的浏览器引擎。与 Selenium 类似,Playwright 同样可以模拟用户行为,但它提供了更简洁的 API 和更少的配置。
二、Playwright 的特点
- 跨浏览器支持:Playwright 支持多种浏览器,包括 Chromium、Firefox 和 Webkit。
- 简洁的 API:Playwright 的 API 设计简洁明了,易于学习和使用。
- 无头模式:Playwright 支持无头模式,可以在没有用户界面的情况下运行,适合用于后台任务。
- 视频录制和截图:Playwright 可以录制浏览器操作的视频和截取页面截图,方便调试和记录。
三、安装与配置
要使用 Python Playwright,首先需要安装它。你可以使用 pip 命令来安装 Playwright:
pip install playwright
安装完成后,你还需要下载对应的浏览器驱动。Playwright 提供了安装驱动的命令行工具,可以通过以下命令安装:
npx playwright install
这将下载并安装 Chromium、Firefox 和 Webkit 的驱动。
四、基本用法
1. 启动浏览器
使用 Playwright 启动浏览器并打开一个页面非常简单。以下是一个示例:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch() # 也可以使用 p.firefox.launch() 或 p.webkit.launch()
page = browser.new_page() # 创建新页面
page.goto("https://www.example.com")
# 在这里可以执行其他操作
browser.close()
2. 页面操作
Playwright 提供了丰富的 API 来操作页面元素和与页面交互。
# 点击元素
element = page.query_selector("button#my-button")
element.click()
# 填写表单
form = page.query_selector("form#my-form")
form.fill({"username": "test", "password": "123456"})
form.submit()
# 导航至新页面
page.goto("https://www.anotherexample.com")
# 获取页面内容
title = page.title()
print(title)
# 截图
page.screenshot(path="screenshot.png")
3. 监听事件
Playwright 还允许你监听浏览器和页面事件。
# 监听页面导航
page.on("request", lambda request: print(f"Request: {request.url}"))
# 监听控制台消息
page.on("console", lambda message: print(f"Console: {message.text()}"))
# 监听页面加载完成
page.on("load", lambda: print("Page loaded"))
4. 异步操作
Playwright 支持异步操作,允许你编写更加灵活和高效的代码。
from playwright.async_api import async_playwright
import asyncio
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
await page.goto("https://www.example.com")
# 在这里可以执行其他异步操作
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
五、常用功能
Playwright 提供了丰富的 API 来操作页面元素和与页面交互。以下是一些常用功能:
1. 页面导航与跳转
page.goto(url, **kwargs)
: 导航到指定的 URL。page.reload()
: 重新加载当前页面。page.wait_for_load_state(state)
: 等待页面达到指定的加载状态(如 ‘networkidle’、‘domcontentloaded’ 等)。
2. 页面元素查询与操作
page.query_selector(selector)
: 使用 CSS 选择器查询页面元素。page.query_selector_all(selector)
: 使用 CSS 选择器查询所有匹配的页面元素。element.click()
: 模拟点击元素。element.fill(values)
: 填充表单元素的值。element.input(value)
: 为元素输入文本。element.press(key, **kwargs)
: 模拟按键操作。element.hover()
: 将鼠标悬停在元素上。
3. 页面内容获取
page.title()
: 获取当前页面的标题。page.content()
: 获取当前页面的 HTML 内容。page.evaluate(expression, **kwargs)
: 在页面上下文中执行 JavaScript 表达式并返回结果。
4. 截图与录屏
page.screenshot(path=None, **kwargs)
: 截取当前页面的截图。browser.start_recording(options)
: 开始录制浏览器操作,生成视频文件。browser.stop_recording()
: 停止录制浏览器操作。
5. 监听浏览器事件
page.on(event, callback)
: 监听指定类型的事件,并在事件发生时调用回调函数。page.off(event, callback)
: 取消监听指定类型的事件。
6. 网络请求拦截与处理
page.route(url, route_handler)
: 拦截匹配指定 URL 的网络请求,并可以自定义处理逻辑。route_handler.abort()
: 中止拦截到的网络请求。route_handler.continue_()
: 继续拦截到的网络请求。route_handler.fulfill(response)
: 使用自定义的响应内容满足拦截到的网络请求。
7. 浏览器上下文管理
browser.new_context(options)
: 创建一个新的浏览器上下文。context.close()
: 关闭浏览器上下文,释放资源。
8. 选择器
Playwright 使用选择器来定位页面元素。选择器可以是 CSS 选择器、XPath 或其他类型。例如,page.query_selector
方法接受一个选择器作为参数,并返回匹配的第一个元素。
9. 等待策略
Playwright 提供了多种等待策略,如 wait_for_load_state
, wait_for_navigation
, wait_for_timeout
, 和 wait_for_selector
等,以确保在继续执行操作之前页面已加载完成或元素已出现。
10. 调试与日志
browser.new_page(headless=False)
: 在非无头模式下打开浏览器,方便进行调试。console.log(message)
: 在控制台输出日志信息。
六、简单使用
更多API功能和使用可以通过官方文档查找,下面提供一些常用API使用方式
- 点击元素:使用
click()
方法点击页面上的元素。
element = page.query_selector("button#my-button")
element.click()
- 填写表单:使用
fill()
方法填写表单。
form = page.query_selector("form#my-form")
form.fill({"username": "test", "password": "123456"})
form.submit()
- 导航至新页面:使用
goto()
方法导航至新页面。
page.goto("https://www.anotherexample.com")
- 获取页面内容:使用
title()
方法获取页面标题,或使用content()
方法获取页面 HTML 内容。
title = page.title()
html_content = page.content()
- 截图:使用
screenshot()
方法截取页面截图。
page.screenshot(path="screenshot.png")
- 监听事件:Playwright 允许你监听浏览器和页面事件,如请求、控制台消息等。
page.on("request", lambda request: print(f"Request: {request.url}"))
page.on("console", lambda message: print(f"Console: {message.text()}"))
- 关闭浏览器: 完成所有操作后,记得关闭浏览器以释放资源:
browser.close()
案例展示
下面提供某滑块登录站点的操作代码,大家可以直观看看各API的具体使用
with sync_playwright() as p:
browser = p.firefox.launch(headless=True) # 关闭无头
context = browser.new_context(
user_agent='Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36',
viewport={'width': 1920, 'height': 1080}
) # 指定user_agent和viewport创建新窗口
page = context.new_page() # 新建标签页
page.goto(self.login_url) # 跳转到指定链接
page.wait_for_timeout(1000) # 等待1秒
# 填充数据
page.fill('css=[id="username"]', username)
page.fill('css=[id="password"]', password)
page.wait_for_timeout(1000) # 等待1秒
# 点击登录
page.click('div.mb-login-btn') # 点击
print('username: {}, password: {}, msg: 点击登录'.format(username, password))
page.wait_for_timeout(2000) # 等待2秒
# 处理滑块
slide_success = False
for i in range(3):
print('username: {}, password: {}, msg: 滑块识别第{}次尝试'.format(username, password, i))
try:
bg = re.search(r'base64,(.*?)"\)', page.get_attribute('.imgBg', 'style')).group(1).strip().replace('"', '') # get_attribute能够根据选择器锁定的标签拿到想要的属性
bth = page.get_attribute('.imgBtn > img', 'src').split('base64,', 1)[1].strip()
slide_x_value = self.identify_gap(base64.b64decode(bg), base64.b64decode(bth))
except Exception as e:
continue
# 根据x长度移动轨迹 获取拖动按钮位置并拖动
slider_btn = page.locator("span.v_rightBtn.btn1") # 定位标签
box = slider_btn.bounding_box() # 获取标签大小属性
page.mouse.move(box['x'] + box['width'] / 2, box['y'] + box['height'] / 2) # 移动鼠标
page.mouse.down() # 按下鼠标
mov_x = box['x'] + box['width'] / 2 + slide_x_value
page.mouse.move(mov_x, box['y'] + box['height'] / 2) # 鼠标按下后滑动距离
page.mouse.up() # 松开鼠标
page.wait_for_timeout(1000)
# 点击账号登录
page.click('.xQuery-master-button')
page.wait_for_timeout(3000)
# 保存storage state 到指定的文件
# storage = context.storage_state(path="auth/state.json")
# print(storage)
if '用户中心' not in page.content(): # page.content()获取标签页全部文本
return False, []
# print({cookie['name']: cookie['value'] for cookie in page.context.cookies()})
cookies_dict = page.context.cookies() # 获取标签页cookie
# 导出登录信息
# storage = context.storage_state(path=r"C:\Users\Admin\Desktop\auth.json")
# 加载登录信息
# context = browser.new_context(storage_state=r"C:\Users\Admin\Desktop\auth.json")
# print(storage)
browser.close() # 关闭浏览器
return True, cookies_dict
本文来自博客园,作者:七夜魔手,转载请注明原文链接:https://www.cnblogs.com/ranbox/p/18461048