snap_html
a robust, modern and high performance Python library for generating image from a html string/html file/url build on top of playwright
View Source
# type: ignore[attr-defined] """a robust, modern and high performance Python library for generating image from a html string/html file/url build on top of `playwright`""" try: from importlib.metadata import PackageNotFoundError, version except ImportError: # pragma: no cover from importlib_metadata import PackageNotFoundError, version try: __version__ = version(__name__) except PackageNotFoundError: # pragma: no cover __version__ = "unknown" from typing import Dict, List, Optional, TypedDict, Union import asyncio import tempfile from dataclasses import dataclass from pathlib import Path from textwrap import dedent from furl import furl from playwright import async_playwright class Resolution(TypedDict): width: int height: int @dataclass class HtmlDoc: html: str @classmethod def create_from_html_parts( cls, body: str, head: str = "", css: str = "", ): prepared_html = f"""\ <html> <head> {head} <style> {css} </style> </head> <body> {body} </body> </html> """ prepared_html = dedent(prepared_html) return cls(html=prepared_html) async def generate_image_batch( targets: List[Union[str, Path, HtmlDoc]], *, resolution=None, query_parameters_list: Optional[List[Optional[Dict]]] = None, output_files: Optional[List[Optional[Union[Path, str]]]] = None, ) -> List[bytes]: """ target could be url, path or html doc """ if resolution is None: resolution = {"width": 1920, "height": 1080} async with async_playwright() as p: browser = await p.chromium.launch() context = await browser.newContext(viewport=resolution) screenshots: List[bytes] = [] for target, query_parameters, output_file in zip( targets, query_parameters_list, output_files ): if isinstance(target, Path): url_address = f"file://{target.absolute()}" elif isinstance(target, HtmlDoc): with tempfile.NamedTemporaryFile( mode="w", suffix=".html", delete=False ) as tf: tf.write(target.html) url_address = f"file://{tf.name}" else: url_address = target await _generate( context, output_file, query_parameters, screenshots, url_address ) await browser.close() return screenshots async def _generate( context, output_file, query_parameters, screenshots, url_address ): page = await context.newPage() furl_url = furl(url_address) if query_parameters: for field_name, value in query_parameters.items(): furl_url.args[field_name] = value await page.goto(furl_url.url) screenshot = await page.screenshot(path=output_file) screenshots.append(screenshot) def generate_image_batch_sync(*args, **kwargs) -> bytes: return asyncio.get_event_loop().run_until_complete( generate_image_batch(*args, **kwargs) ) async def generate_image( target: Union[str, Path, HtmlDoc], *, resolution: Resolution, query_parameters: Optional[Dict] = None, output_file: Optional[Union[Path, str]] = None, ) -> bytes: screenshots = await generate_image_batch( [target], resolution=resolution, query_parameters_list=[query_parameters], output_files=[output_file], ) return screenshots[0] def generate_image_sync(*args, **kwargs) -> bytes: return asyncio.get_event_loop().run_until_complete( generate_image(*args, **kwargs) )
class
Resolution(builtins.dict):
View Source
class Resolution(TypedDict): width: int height: int
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)
width: int
height: int
Inherited Members
- builtins.dict
- dict
- get
- setdefault
- pop
- popitem
- keys
- items
- values
- update
- fromkeys
- clear
- copy
class
HtmlDoc:
View Source
class HtmlDoc: html: str @classmethod def create_from_html_parts( cls, body: str, head: str = "", css: str = "", ): prepared_html = f"""\ <html> <head> {head} <style> {css} </style> </head> <body> {body} </body> </html> """ prepared_html = dedent(prepared_html) return cls(html=prepared_html)
HtmlDoc(html: str)
HtmlDoc(html: str)
html: str
@classmethod
def
create_from_html_parts(cls, body: str, head: str = '', css: str = ''):
View Source
@classmethod def create_from_html_parts( cls, body: str, head: str = "", css: str = "", ): prepared_html = f"""\ <html> <head> {head} <style> {css} </style> </head> <body> {body} </body> </html> """ prepared_html = dedent(prepared_html) return cls(html=prepared_html)
async def
generate_image_batch(
targets: List[Union[str, pathlib.Path, snap_html.HtmlDoc]],
*,
resolution=None,
query_parameters_list: Union[List[Union[Dict, NoneType]], NoneType] = None,
output_files: Union[List[Union[pathlib.Path, str, NoneType]], NoneType] = None
) -> List[bytes]:
View Source
async def generate_image_batch( targets: List[Union[str, Path, HtmlDoc]], *, resolution=None, query_parameters_list: Optional[List[Optional[Dict]]] = None, output_files: Optional[List[Optional[Union[Path, str]]]] = None, ) -> List[bytes]: """ target could be url, path or html doc """ if resolution is None: resolution = {"width": 1920, "height": 1080} async with async_playwright() as p: browser = await p.chromium.launch() context = await browser.newContext(viewport=resolution) screenshots: List[bytes] = [] for target, query_parameters, output_file in zip( targets, query_parameters_list, output_files ): if isinstance(target, Path): url_address = f"file://{target.absolute()}" elif isinstance(target, HtmlDoc): with tempfile.NamedTemporaryFile( mode="w", suffix=".html", delete=False ) as tf: tf.write(target.html) url_address = f"file://{tf.name}" else: url_address = target await _generate( context, output_file, query_parameters, screenshots, url_address ) await browser.close() return screenshots
target could be url, path or html doc
def
generate_image_batch_sync(*args, **kwargs) -> bytes:
View Source
def generate_image_batch_sync(*args, **kwargs) -> bytes: return asyncio.get_event_loop().run_until_complete( generate_image_batch(*args, **kwargs) )
async def
generate_image(
target: Union[str, pathlib.Path, snap_html.HtmlDoc],
*,
resolution: snap_html.Resolution,
query_parameters: Union[Dict, NoneType] = None,
output_file: Union[pathlib.Path, str, NoneType] = None
) -> bytes:
View Source
async def generate_image( target: Union[str, Path, HtmlDoc], *, resolution: Resolution, query_parameters: Optional[Dict] = None, output_file: Optional[Union[Path, str]] = None, ) -> bytes: screenshots = await generate_image_batch( [target], resolution=resolution, query_parameters_list=[query_parameters], output_files=[output_file], ) return screenshots[0]
def
generate_image_sync(*args, **kwargs) -> bytes:
View Source
def generate_image_sync(*args, **kwargs) -> bytes: return asyncio.get_event_loop().run_until_complete( generate_image(*args, **kwargs) )