Skip to content

Commit

Permalink
Merge origin master
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxime Courtet committed Apr 30, 2019
2 parents 2ac2193 + 2d816a1 commit 94027c4
Show file tree
Hide file tree
Showing 4 changed files with 239 additions and 81 deletions.
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,11 @@ The documentation is accessible [here](https://screamshot.readthedocs.io/en/late
The server must be launched using --nothreading and --noreload as argument.
```
# views.py in a Django project
import asyncio
from django.http import HttpResponse
from screamshot import generate_bytes_img_prom
import asyncio
from screamshot import generate_bytes_img_prom
def home(request):
loop = asyncio.get_event_loop()
Expand All @@ -66,11 +65,21 @@ def home(request):
generate_bytes_img_prom('https://www.google.fr', future))
loop.run_until_complete(future)
print(future.result())
return HttpResponse('Done')
return HttpResponse(future.result(), content_type='image')
```
Or using the already wrapped function
```
# views.py in a Django project
from django.http import HttpResponse
from screamshot import generate_bytes_img__django_wrap
def home(request):
img = generate_bytes_img__django_wrap('https://www.google.fr')
return HttpResponse(img, content_type='image')
```


#### Using Gunicorn

With [Gunicorn](https://gunicorn.org/) there isn't the thread related problems and we don't need to use the --nothreading and --noreload arguments.
With [Gunicorn](https://gunicorn.org/) there isn't the thread related problems so we don't need to use the --nothreading and --noreload arguments.
14 changes: 12 additions & 2 deletions screamshot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,18 @@
__version__ = "0.1.4"


from screamshot.generate_bytes_img_functions import generate_bytes_img, generate_bytes_img_prom
from screamshot.generate_bytes_img_functions import (
generate_bytes_img,
generate_bytes_img_prom,
generate_bytes_img_django_wrap,
)
from screamshot.serializer import serialize, deserialize


__all__ = ['generate_bytes_img', 'generate_bytes_img_prom', 'serialize', 'deserialize']
__all__ = [
"generate_bytes_img",
"generate_bytes_img_prom",
"generate_bytes_img_django_wrap",
"serialize",
"deserialize",
]
108 changes: 75 additions & 33 deletions screamshot/generate_bytes_img_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
generate_bytes_img and generate_bytes_img_prom functions.
"""
from typing import Any
from asyncio.futures import Future
from asyncio import get_event_loop, ensure_future, Future

from pyppeteer.page import Page
from pyppeteer.browser import Browser
Expand All @@ -12,30 +12,30 @@

def _parse_parameters(**kwargs) -> dict:
arg_viewport = {}
if 'width' in kwargs:
arg_viewport.update({'width': kwargs.pop('width')})
if 'height' in kwargs:
arg_viewport.update({'height': kwargs.pop('height')})
if "width" in kwargs:
arg_viewport.update({"width": kwargs.pop("width")})
if "height" in kwargs:
arg_viewport.update({"height": kwargs.pop("height")})

if 'wait_until' in kwargs:
wait_until = kwargs.pop('wait_until')
if "wait_until" in kwargs:
wait_until = kwargs.pop("wait_until")
if not isinstance(wait_until, list):
wait_until = [wait_until]
else:
wait_until = ['load']
wait_until = ["load"]

screenshot_options = {'fullPage': kwargs.get('full_page', False)}
if 'path' in kwargs:
path = kwargs.pop('path')
screenshot_options.update({'path': path})
screenshot_options = {"fullPage": kwargs.get("full_page", False)}
if "path" in kwargs:
path = kwargs.pop("path")
screenshot_options.update({"path": path})

selector = None
if 'selector' in kwargs:
selector = kwargs.pop('selector')
if "selector" in kwargs:
selector = kwargs.pop("selector")

wait_for = None
if 'wait_for' in kwargs:
wait_for = kwargs.pop('wait_for')
if "wait_for" in kwargs:
wait_for = kwargs.pop("wait_for")

credentials = {}
if 'credentials' in kwargs:
Expand All @@ -48,41 +48,41 @@ def _parse_parameters(**kwargs) -> dict:
credentials.update({'credentials_data': credentials_data})

return {
'arg_viewport': arg_viewport,
'screenshot_options': screenshot_options,
'selector': selector,
'wait_for': wait_for,
'wait_until': wait_until,
'credentials': credentials,
"arg_viewport": arg_viewport,
"screenshot_options": screenshot_options,
"selector": selector,
"wait_for": wait_for,
"wait_until": wait_until,
"credentials": credentials,
}


async def _page_manager(browser: Browser, url: str, params: dict) -> Page:
page = await browser.newPage()

arg_viewport = params.get('arg_viewport')
arg_viewport = params.get("arg_viewport")
if arg_viewport:
await page.setViewport(arg_viewport)

credentials = params.get('credentials')
credentials = params.get("credentials")
if credentials:
credentials_data = credentials.get('credentials_data')
if credentials.get('login'):
credentials_data = credentials.get("credentials_data")
if credentials.get("login"):
await page.authenticate(credentials_data)
if credentials.get('token_in_header'):
if credentials.get("token_in_header"):
await page.setExtraHTTPHeaders(credentials_data)

await page.goto(url, waitUntil=params.get('wait_until'))
await page.goto(url, waitUntil=params.get("wait_until"))

wait_for = params.get('wait_for')
wait_for = params.get("wait_for")
if wait_for:
await page.waitForSelector(wait_for)

return page


async def _selector_manager(page: Page, params: dict) -> Any:
selector = params.get('selector')
selector = params.get("selector")
if selector:
return await page.querySelector(selector)

Expand All @@ -102,7 +102,7 @@ async def generate_bytes_img(url: str, **kwargs) -> bytes:
:param credentials: If the website uses "login authentication", you can specify two fields: \
`username` and `password`. Otherwise, if it uses a "token identification" that must be \
specified in the header, please indicate into `credentials` the field that should be \
passed to the header, as well as a `token_in_header` field equal to `on`.
passed to the header, as well as a `token_in_header` field equal to `True`.
:type credentials: dict
:param width: optionnal, the window's width
Expand Down Expand Up @@ -154,7 +154,7 @@ async def main():

element = await _selector_manager(page, params)

image = await element.screenshot(options=params.get('screenshot_options'))
image = await element.screenshot(options=params.get("screenshot_options"))

await page.close()
return image
Expand All @@ -177,7 +177,7 @@ async def generate_bytes_img_prom(url: str, future: Future, **kwargs):
:param credentials: If the website uses "login authentication", you can specify two fields: \
`username` and `password`. Otherwise, if it uses a "token identification" that must be \
specified in the header, please indicate into `credentials` the field that should be \
passed to the header, as well as a `token_in_header` field equal to `on`.
passed to the header, as well as a `token_in_header` field equal to `True`.
:type credentials: dict
:param width: optionnal, the window's width
Expand Down Expand Up @@ -228,3 +228,45 @@ def home(request):
img = await generate_bytes_img(url, **kwargs)

future.set_result(img)


def generate_bytes_img_django_wrap(url: str, **kwargs):
"""
This function takes a screenshot and returns it as a `bytes` object in \
synchorouns mode, usable directly in django
:param url: mandatory, the website's url
:type url: str
:param path: optional, the path to the image output
:type path: str
:param width: optionnal, the window's width
:type width: int
:param height: optionnal, the window's height
:type height: int
:param selector: optionnal, CSS3 selector, item whose screenshot is taken
:type selector: str
:param wait_for: optionnal, CSS3 selector, item to wait before taking the screenshot
:type wait_for: str
:param wait_until: optionnal, define how long you wait for the page to be loaded should \
be either load, domcontentloaded, networkidle0 or networkidle2
:type wait_until: str or list(str)
:returns: the binary code of the image
:retype: `bytes`
"""

loop = get_event_loop()
future = Future()

ensure_future(generate_bytes_img_prom(url, future, **kwargs))
loop.run_until_complete(future)

return future.result()
Loading

0 comments on commit 94027c4

Please sign in to comment.