Giter Club home page Giter Club logo

playwright-python's Introduction

๐ŸŽญ Playwright for Python

PyPI version PyPI pyversions Join Slack Chromium version Firefox version WebKit version

Playwright is a Python library to automate Chromium, Firefox and WebKit with a single API. Playwright is built to enable cross-browser web automation that is ever-green, capable, reliable and fast.

Linux macOS Windows
Chromium 86.0.4238.0 โœ… โœ… โœ…
WebKit 14.0 โœ… โœ… โœ…
Firefox 80.0b8 โœ… โœ… โœ…

Headless execution is supported for all the browsers on all platforms.

Installation

pip install playwright
python -m playwright install

This installs Playwright and browser binaries for Chromium, Firefox and WebKit. Once installed, you can import Playwright in a Python script and automate web browser interactions. Playwright requires Python 3.7+.

Capabilities

Playwright is built to automate the broad and growing set of web browser capabilities used by Single Page Apps and Progressive Web Apps.

  • Scenarios that span multiple page, domains and iframes
  • Auto-wait for elements to be ready before executing actions (like click, fill)
  • Intercept network activity for stubbing and mocking network requests
  • Emulate mobile devices, geolocation, permissions
  • Support for web components via shadow-piercing selectors
  • Native input events for mouse and keyboard
  • Upload and download files

Usage

Pytest

Playwright can be used as a library in your application or as a part of the testing solution. We recommend using our Pytest plugin for testing.

As a library, Playwright offers both blocking (synchronous) API and asyncio API (async/await). You can pick the one that works best for you. They are identical in terms of capabilities and only differ in a way one consumes the API.

Below are some of the examples on how these variations of the API can be used:

Sync variant

from playwright import sync_playwright

with sync_playwright() as p:
    for browser_type in [p.chromium, p.firefox, p.webkit]:
        browser = browser_type.launch()
        page = browser.newPage()
        page.goto('http://whatsmyuseragent.org/')
        page.screenshot(path=f'example-{browser_type.name}.png')
        browser.close()

Async variant

import asyncio
from playwright import async_playwright

async def main():
    async with async_playwright() as p:
        for browser_type in [p.chromium, p.firefox, p.webkit]:
            browser = await browser_type.launch()
            page = await browser.newPage()
            await page.goto('http://whatsmyuseragent.org/')
            await page.screenshot(path=f'example-{browser_type.name}.png')
            await browser.close()

asyncio.get_event_loop().run_until_complete(main())

Using pytest-playwright

def test_playwright_is_visible_on_google(page):
    page.goto("https://www.google.com")
    page.type("input[name=q]", "Playwright GitHub")
    page.click("input[type=submit]")
    page.waitForSelector("text=microsoft/Playwright")

For more information on pytest-playwright, see GitHub.

REPL support without context managers

For scripting purposes, it is also possible to start and stop Playwright manually without relying on the indentation of the REPL.

from playwright import sync_playwright

playwright = sync_playwright().start()
for browser_type in [playwright.chromium, playwright.firefox, playwright.webkit]:
    browser = browser_type.launch()
    page = browser.newPage()
    page.goto("http://whatsmyuseragent.org/")
    page.screenshot(path=f"example-{browser_type.name}.png")
    browser.close()

playwright.stop()

More examples

Mobile and geolocation

This snippet emulates Mobile Safari on a device at a given geolocation, navigates to maps.google.com, performs action and takes a screenshot.

from playwright import sync_playwright

with sync_playwright() as p:
    iphone_11 = p.devices['iPhone 11 Pro']
    browser = p.webkit.launch(headless=False)
    context = browser.newContext(
        **iphone_11,
        locale='en-US',
        geolocation={ 'longitude': 12.492507, 'latitude': 41.889938 },
        permissions=['geolocation']
    )
    page = context.newPage()
    page.goto('https://maps.google.com')
    page.click('text="Your location"')
    page.screenshot(path='colosseum-iphone.png')
    browser.close()

The asyncio variant:

import asyncio
from playwright import async_playwright

async def main():
    async with async_playwright() as p:
        iphone_11 = p.devices['iPhone 11 Pro']
        browser = await p.webkit.launch(headless=False)
        context = await browser.newContext(
            **iphone_11,
            locale='en-US',
            geolocation={ 'longitude': 12.492507, 'latitude': 41.889938 },
            permissions=['geolocation']
        )
        page = await context.newPage()
        await page.goto('https://maps.google.com')
        await page.click('text="Your location"')
        await page.screenshot(path='colosseum-iphone.png')
        await browser.close()

asyncio.get_event_loop().run_until_complete(main())

Evaluate in browser context

This code snippet navigates to example.com in Firefox, and executes a script in the page context.

from playwright import sync_playwright

with sync_playwright() as p:
    browser = p.firefox.launch()
    page = browser.newPage()
    page.goto('https://www.example.com/')
    dimensions = page.evaluate('''() => {
      return {
        width: document.documentElement.clientWidth,
        height: document.documentElement.clientHeight,
        deviceScaleFactor: window.devicePixelRatio
      }
    }''')
    print(dimensions)
    browser.close()

The asyncio variant:

import asyncio
from playwright import async_playwright

async def main():
    async with async_playwright() as p:
        browser = await p.firefox.launch()
        page = await browser.newPage()
        await page.goto('https://www.example.com/')
        dimensions = await page.evaluate('''() => {
          return {
            width: document.documentElement.clientWidth,
            height: document.documentElement.clientHeight,
            deviceScaleFactor: window.devicePixelRatio
          }
        }''')
        print(dimensions)
        await browser.close()

asyncio.get_event_loop().run_until_complete(main())

Intercept network requests

This code snippet sets up request routing for a Chromium page to log all network requests.

from playwright import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.newPage()

    def log_and_continue_request(route, request):
      print(request.url)
      route.continue_()

    # Log and continue all network requests
    page.route('**', lambda route, request: log_and_continue_request(route, request))

    page.goto('http://todomvc.com')
    browser.close()

The asyncio variant:

import asyncio
from playwright import async_playwright

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        page = await browser.newPage()

        def log_and_continue_request(route, request):
            print(request.url)
            asyncio.create_task(route.continue_())

        # Log and continue all network requests
        await page.route('**', lambda route, request: log_and_continue_request(route, request))

        await page.goto('http://todomvc.com')
        await browser.close()

asyncio.get_event_loop().run_until_complete(main())

Documentation

We are in the process of converting the documentation from the Node.js form to the Python one. But you can go ahead and use the Node.js documentation because the API is pretty much the same. You might have noticed that Playwright uses non-Python naming conventions, camelCase instead of the snake_case for its methods. We recognize that this is not ideal, but it was done deliberately, so that you could rely upon the stack overflow answers and the documentation of the Playwright for Node.js.

Understanding examples from the JavaScript documentation

You can use all the same methods and arguments as documented, just remember that since Python allows named arguments, we didn't need to put options parameter into every call as we had to in the Node.js version:

So when you see example like this in JavaScript

await webkit.launch({ headless: false });

It translates into Python like this:

webkit.launch(headless=False)

If you are using an IDE, it'll suggest parameters that are available in every call.

Evaluating functions

Another difference is that in the JavaScript version, page.evaluate accepts JavaScript functions, while this does not make any sense in the Python version.

In JavaScript it will be documented as:

const result = await page.evaluate(([x, y]) => {
  return Promise.resolve(x * y);
}, [7, 8]);
console.log(result); // prints "56"

And in Python that would look like:

result = page.evaluate("""
    ([x, y]) => {
        return Promise.resolve(x * y);
    }""",
    [7, 8])
print(result) # prints "56"

The library will detect that what are passing it is a function and will invoke it with the given parameters. You can opt out of this function detection and pass force_expr=True to all evaluate functions, but you probably will never need to do that.

Using context managers

Python enabled us to do some of the things that were not possible in the Node.js version and we used the opportunity. Instead of using the page.waitFor* methods, we recommend using corresponding page.expect_* context manager.

In JavaScript it will be documented as:

const [ download ] = await Promise.all([
  page.waitForEvent('download'), // <-- start waiting for the download
  page.click('button#delayed-download') // <-- perform the action that directly or indirectly initiates it.
]);
const path = await download.path();

And in Python that would look much simpler:

with page.expect_download() as download_info:
    page.click("button#delayed-download")
download = download_info.value
path = download.path()

Similarly, for waiting for the network response:

const [response] = await Promise.all([
  page.waitForResponse('**/api/fetch_data'),
  page.click('button#update'),
]);

Becomes

with page.expect_response("**/api/fetch_data"):
    page.click("button#update")

Is Playwright for Python ready?

Yes, Playwright for Python is ready. We are still not at the version v1.0, so minor breaking API changes could potentially happen. But a) this is unlikely and b) we will only do that if we know it improves your experience with the new library. We'd like to collect your feedback before we freeze the API for v1.0.

Note: We don't yet support some of the edge-cases of the vendor-specific APIs such as collecting chromium trace, coverage report, etc.

Resources

playwright-python's People

Contributors

pavelfeldman avatar mxschmitt avatar rwoll avatar microsoftopensource avatar dgozman avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.