playwright is Microsoft’s open source automated web application testing framework, supporting the mainstream Python, NodeJS, Java and other languages, the official documentation has been very well developed, this article will quickly share some common usage in production development.

1. Installation

The version of Python used is 3.8.6.

Windows 7 supports up to version 3.8.10, for compatibility reasons try to use versions below 3.8.10

Install playwright using pip as follows.

1
2
pip3 install playwright
playwright install

Example 1: Use the traditional synchronisation method.

1
2
3
4
5
6
7
8
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("http://playwright.dev")
    print(page.title())
    browser.close()

Example 2: Using async/await asynchronously.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        page = await browser.new_page()
        await page.goto("http://playwright.dev")
        print(await page.title())
        await browser.close()

asyncio.run(main())

Using async is a simple and effective way to increase concurrency, playwright is network IO intensive in most scenarios, but writing with async is more demanding on the developer and debug is not as convenient as traditional synchronous methods

Whether or not to use asynchronous writing depends on your application framework and development needs.

2. Use

2.1. element selection

Documentation reference: https://playwright.dev/python/docs/api/class-locator

The following is an example of a search for chancel.me at bing.com and outputting the first search result.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    b = p.chromium.launch()
    page = b.new_page()
    page.goto('https://bing.com')

    page.locator('#sb_form_q').fill('chancel.me') # fills the string
    page.locator('#search_icon').click() # select and click

    print(page.locator('[class=b_algo]').nth(0).text_content()) # Get text after selection

The output is shown below.

1
syncmemo - Chancel's bloghttps://memo.chancel.me/help ...

2.2. Cookies management

Documentation reference: https://playwright.dev/python/docs/api/class-browsercontext

Automation usually involves saving cookies, and playwright needs to create a new context to get them.

The following is an example of a get/set operation for cookies

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from playwright.sync_api import sync_playwright

cookies = None

with sync_playwright() as p:
    b = p.chromium.launch()
    c = b.new_context()
    page = c.new_page()
    page.goto('https://www.chancel.me/')
    cookies = c.cookies()

    print(cookies)

with sync_playwright() as p:
    b = p.chromium.launch()
    c = b.new_context()
    page = c.new_page()
    c.add_cookies(cookies)
    page.goto('https://www.chancel.me/')
    cookies = c.cookies()

    print(cookies)

The output is shown below.

1
[{'name': 'TOKEN', 'value': 'c263e3a6-c88d-11ed-8979-6ee82343e005', 'domain': 'www.chancel.me', 'path': '/', 'expires': 1684658669.818441, 'httpOnly': True, 'secure': True, 'sameSite': 'Lax'}]

2.3. document download

Reference documentation: https://playwright.dev/python/docs/api/class-download

As an example of downloading a Github binary package.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from playwright.sync_api import sync_playwright

cookies = None

with sync_playwright() as p:
    b = p.chromium.launch()
    page = b.new_page()
    page.goto('https://github.com/chancelyg/godaddy-ddns/releases')
    with page.expect_download() as download_info:
        page.locator('[href="/chancelyg/godaddy-ddns/releases/download/v23.01.06/godaddy-ddns_Darwin_arm64.tar.gz"]').click()
    download_info.value.save_as('godaddy-ddns_Darwin_arm64.tar.gz')

2.4. Video recordings and screenshots

Reference document: https://playwright.dev/python/docs/api/class-video

When developing playwright you will often need to take screenshots to confirm that the automation process is working properly.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from playwright.sync_api import sync_playwright

# Screenshots
with sync_playwright() as p:
    b = p.chromium.launch()
    page = b.new_page()
    page.goto('https://www.chancel.me')
    page.screenshot(path='screenshot.png')

# Record video
with sync_playwright() as p:
    b = p.chromium.launch()
    page = b.new_page(record_video_dir="videos", record_video_size={"width": 640, "height": 480})
    page.goto('https://www.google.com')
    page.goto('https://www.chancel.me')

3. Running in Docker

Reference documentation: https://playwright.dev/docs/docker#image-tags

playwright has an official image, take mcr.microsoft.com/playwright/python:v1.31.0-focal as an example, and run a uvicorn gateway application with the following Dockerfile file

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
FROM mcr.microsoft.com/playwright/python:v1.31.0-focal

ENV LANG en_US.UTF-8

WORKDIR /app

COPY ./web /app/web
COPY ./requirements.txt /app/requirements.txt


RUN pip3 install -r /app/requirements.txt && \
playwright install && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime


CMD ["uvicorn", "web:app", "--host=0.0.0.0", "--port=5000"]