Scrapy与分布式开发(2.5):自动化工具playwright

Python Playwright 模块详细讲解

一、简介

Playwright 是一个无头浏览器测试库,它允许你使用 Python 脚本控制浏览器自动化,执行各种浏览器操作,如点击、填写表单、导航至页面等。Playwright 支持 Chromium (包括 Chrome 和 Edge)、Firefox 和 Webkit (包括 Safari) 这三种主流的浏览器引擎。与 Selenium 类似,Playwright 同样可以模拟用户行为,但它提供了更简洁的 API 和更少的配置。

二、Playwright 的特点

  1. 跨浏览器支持:Playwright 支持多种浏览器,包括 Chromium、Firefox 和 Webkit。
  2. 简洁的 API:Playwright 的 API 设计简洁明了,易于学习和使用。
  3. 无头模式:Playwright 支持无头模式,可以在没有用户界面的情况下运行,适合用于后台任务。
  4. 视频录制和截图: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使用方式

  1. 点击元素:使用 click() 方法点击页面上的元素。
element = page.query_selector("button#my-button")
element.click()
  1. 填写表单:使用 fill() 方法填写表单。
form = page.query_selector("form#my-form")
form.fill({"username": "test", "password": "123456"})
form.submit()
  1. 导航至新页面:使用 goto() 方法导航至新页面。
page.goto("https://www.anotherexample.com")
  1. 获取页面内容:使用 title() 方法获取页面标题,或使用 content() 方法获取页面 HTML 内容。
title = page.title()
html_content = page.content()
  1. 截图:使用 screenshot() 方法截取页面截图。
page.screenshot(path="screenshot.png")
  1. 监听事件:Playwright 允许你监听浏览器和页面事件,如请求、控制台消息等。
page.on("request", lambda request: print(f"Request: {request.url}"))
page.on("console", lambda message: print(f"Console: {message.text()}"))
  1. 关闭浏览器: 完成所有操作后,记得关闭浏览器以释放资源:
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('&quot', '')  # 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
posted @ 2024-08-22 09:44  七夜魔手  阅读(55)  评论(0编辑  收藏  举报  来源