Keep Pyppeteer browser open indefinitely between Flask requests

605 views Asked by At

By default Pyppeteer opens a new browser for every screenshot, on my setup, this increases the screenshot time by 100% compared to having the browser open.

Therefore, my question is: How would I keep Chrome/Pyppeteer browser open (globally) and just use the open browser to take screenshots instead of opening a new browser for every screenshot?

We have a Flask GET endpoint with parameters:

targetUrl --> The page Chrome will take a screenshot from

intervalInside --> How many screenshots to take without closing the browser

intervalOutside --> How many screenshots to take while closing the browser for every screenshot

Here is my current code, I am not even sure if this is possible without having to use threads. Any ideas?

Example: http://127.0.0.1:5000/?targetUrl=https://google.com&intervalInside=1&intervalOutside=1

from asyncio import new_event_loop
from traceback import format_exc
from time import time
from flask import Flask
from flask import request
from pyppeteer import launch

loop = new_event_loop()
app = Flask(__name__)

# Change the chromium path to fit your needs
# If you are on a MAC you can run
# brew install chromium
# chromeiumPath = "/usr/bin/chromium-browser"
chromeiumPath = "/opt/homebrew/bin/chromium"


async def takeScreenshotPyP(targetUrl, intervalInside):
    try:
        print(f"Generating screenshot from targetUrl: {targetUrl}")
        browser = await launch(
            args=[
                "--no-sandbox",
                "--single-process",
                "--disable-dev-shm-usage",
                "--disable-gpu",
                "--no-zygote",
            ],
            userDataDir="/tmp",
            autoClose=False,
            headless=True,
            ignoreHTTPSErrors=True,
            executablePath=chromeiumPath,
            logLevel="ERROR",
            handleSIGINT=False,
            handleSIGTERM=False,
            handleSIGHUP=False
        )
        for _ in range(intervalInside):
            page = await browser.newPage()
            await page.goto(targetUrl)
            await page.screenshot({"fullPage": True, "path": f"screen_{round(time() * 1000)}.jpeg", "type": "jpeg"})
        await browser.close()
    except Exception:
        print(f"Error taking screenshot: {format_exc()}")


@app.route("/", methods=["GET"])
def takeScreenshot():
    if request.method == "GET":
        requestArgs = request.args.to_dict()
        targetUrl = requestArgs.get("targetUrl")
        intervalInside = requestArgs.get("intervalInside")
        intervalOutside = requestArgs.get("intervalOutside")
        try:
            intervalInside = int(intervalInside)
        except Exception:
            intervalInside = 1
        try:
            intervalOutside = int(intervalOutside)
        except Exception:
            intervalOutside = 1
        if targetUrl:
            startTime = time()
            for _ in range(intervalOutside):
                loop.run_until_complete(takeScreenshotPyP(targetUrl, intervalInside))
            print(f"Taking the screenshot took: {time() - startTime}")
            return "Screenshot taken and saved to file!"
    return "Bad request", 401


if __name__ == "__main__":
    app.run(debug=True)
0

There are 0 answers