【Playwright+Python】系列教程(二)手把手帶你寫一個指令碼

久曲健發表於2024-06-24

一、如何使用代理方式開啟網頁

playwright.chromium.launch() 中傳入 proxy 引數即可,示例程式碼如下:

1、同步寫法:

from playwright.sync_api import sync_playwright

proxy = {'server': 'http:/127.0.0.1:8080'}


def run():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False, proxy=proxy)
        page = browser.new_page()

        page.goto('https://www.baidu.com')

        title = page.title()
        if "百度" in title:
            print("開啟百度成功")
        else:
            print("開啟百度失敗")

        browser.close()


run()

2、非同步寫法:

from playwright.async_api import async_playwright
import asyncio

proxy = {'server': 'http:/127.0.0.1:8080'}


async def run():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=False, proxy=proxy)
        page = await browser.new_page()

        await page.goto('https://www.baidu.com')

        title = await page.title()
        if "百度" in title:
            print("開啟百度成功")
        else:
            print("開啟百度失敗")

        await browser.close()


asyncio.get_event_loop().run_until_complete(run())

二、同步和非同步寫法對比

1、同步的優點:

  • 程式碼結構簡單易懂,不需要學習async/await語法
  • 適用於小規模或簡單任務
  • 除錯和理解同步程式碼更簡單

2、非同步的優點:

  • 能更高效地利用系統資源,避免阻塞等待IO
  • 對於長時間操作如網路請求更高效
  • 可以支援併發執行多個任務
  • 對於大規模和複雜系統更有利

3、區別

  • 對於小任務和學習用途,同步程式碼結構更簡單。
  • 對於需要長時間IO等待的任務(如網路請求),使用非同步可以更高效。
  • 對於需要支援高併發的系統(如網站),使用非同步模型可以支援更多併發連線。
  • 多執行緒同步會帶來鎖的問題,而非同步避免了鎖的使用。
  • 非同步的FUTURE模式也更易於擴充套件性好,支援動態增加回撥函式。

4、總結

  • 小任務用同步
  • 長時間IO任務用非同步
  • 高併發系統用非同步
  • 以後的功能擴充套件考慮非同步更靈活

一般來說對於現代化系統,非同步程式設計模型將是主流趨勢。但同步在某些場景也同樣易用。選擇時要根據具體需求來權衡。

三、寫一個用例

1、示例指令碼

算是個入門的例子,關於每句話的意思,看我註釋即可,示例程式碼如下:

import re
from playwright.sync_api import Page, expect, sync_playwright

proxy = {'server': 'http://127.0.0.1:8080'}


def test_baidu():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False, proxy=proxy)
        page = browser.new_page()
        # 跳轉到baidu頁面
        page.goto("https://www.baidu.com/")
        # 點選輸入框
        page.locator("#kw").click()
        # 輸入框輸入selenium
        page.locator("#kw").fill("selenium")
        # 點選百度一下查詢按鈕
        page.get_by_role("button", name="百度一下").click()
        # 驗證輸入框是否輸入selenium
        expect(page.locator("#kw")).to_have_value("selenium")
        # 驗證頁面是否包含文字“大家還在搜”
        expect(page.locator("#content_left")).to_contain_text("大家還在搜")
        # 退出瀏覽器
        browser.close()

注意:
測試類和測試方法都要用test_ 字首命名

2、基本操作

這是 Playwright 常用操作列表,請注意,還有許多其他操作,請務必檢視定位器 API 部分以瞭解更多相關資訊。

操作 描述
locator.check() 選中輸入核取方塊
locator.click() 點選元素
locator.uncheck() 取消選中輸入核取方塊
locator.hover() 將滑鼠懸停在元素上
locator.fill() 填寫表單欄位,輸入文字
locator.focus() 聚焦元素
locator.press() 按下單個鍵
locator.set_input_files() 選擇要上傳的檔案
locator.select_option() 從下拉選單中選擇選項

3、斷言操作

斷言 描述
expect(locator).to_be_checked() 核取方塊處於選中狀態
expect(locator).to_be_enabled() 控制元件已啟用
expect(locator).to_be_visible() 元素可見
expect(locator).to_contain_text() 元素包含文字
expect(locator).to_have_attribute() 元素具有屬性
expect(locator).to_have_count() 元素列表已給出長度
expect(locator).to_have_text() 元素匹配文字
expect(locator).to_have_value() 輸入元素具有值
expect(page).to_have_title() 頁面有標題
expect(page).to_have_url() 頁面有 URL

4、fixtures夾具的使用

示例程式碼:

import pytest
from playwright.sync_api import Page, expect, sync_playwright


@pytest.fixture(scope="function", autouse=True)
def before_each_after_each(page: Page):
    print("before the test runs")

    page.goto("https://www.baidu.com/")
    yield

    print("after the test runs")


def test_main_navigation(page: Page):
    page.locator("#kw").fill("久曲健 部落格園")
    page.get_by_role("button", name="百度一下").click()
    expect(page.locator("#content_left")).to_contain_text("久曲健 - 部落格園")

程式碼解釋:

  • 定義了一個名為 before_each_after_each 的 fixture(夾具),它的作用域是每個測試函式,並且設定為自動應用於每個測試函式。
  • 在這個 fixture 中: 列印 "before the test runs",表示測試執行前執行的操作。 使用 page.goto("https://www.baidu.com/") 開啟百度首頁。
  • yield 關鍵字在這個 fixture 執行期間掛起,等待測試函式執行。測試函式將在 fixture 的環境下執行。

相關文章