Skip to content

Commit

Permalink
--js-selector prototype, refs #43
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Apr 9, 2022
1 parent 1bf8020 commit 8a61c7e
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ Options:
-o, --output FILE
-s, --selector TEXT Take shot of first element matching this CSS
selector
--js-selector TEXT Take shot of first element matching this JS
(el) expression
-p, --padding INTEGER When using selectors, add this much padding in
pixels
-j, --javascript TEXT Execute this JS prior to taking the shot
Expand Down
42 changes: 41 additions & 1 deletion shot_scraper/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ def cli():
help="Take shot of first element matching this CSS selector",
multiple=True,
)
@click.option(
"js_selectors",
"--js-selector",
help="Take shot of first element matching this JS (el) expression",
multiple=True,
)
@click.option(
"-p",
"--padding",
Expand Down Expand Up @@ -119,6 +125,7 @@ def shot(
width,
height,
selectors,
js_selectors,
padding,
javascript,
retina,
Expand Down Expand Up @@ -162,6 +169,7 @@ def shot(
shot = {
"url": url,
"selectors": selectors,
"js_selectors": js_selectors,
"javascript": javascript,
"width": width,
"height": height,
Expand Down Expand Up @@ -570,6 +578,10 @@ def take_shot(
if shot.get("selector"):
selectors.append(shot["selector"])

js_selectors = shot.get("js_selectors") or []
if shot.get("js_selector"):
js_selectors.append(shot["js_selector"])

if not use_existing_page:
page = context_or_page.new_page()
else:
Expand Down Expand Up @@ -600,9 +612,15 @@ def take_shot(
if not return_bytes:
screenshot_args["path"] = output

if not selectors:
if not selectors and not js_selectors:
screenshot_args["full_page"] = full_page

if js_selectors:
# Evaluate JavaScript adding classes we can select on
js_selector_javascript, extra_selectors = _js_selector_javascript(js_selectors)
selectors.extend(extra_selectors)
_evaluate_js(page, js_selector_javascript)

if selectors:
# Use JavaScript to create a box around those elements
selector_javascript, selector_to_shoot = _selector_javascript(
Expand All @@ -626,6 +644,28 @@ def take_shot(
click.echo(message, err=True)


def _js_selector_javascript(js_selectors):
extra_selectors = []
js_blocks = []
for js_selector in js_selectors:
klass = "js-selector-{}".format(secrets.token_hex(16))
extra_selectors.append(".{}".format(klass))
js_blocks.append(
textwrap.dedent(
"""
Array.from(
document.getElementsByTagName('*')
).find(el => {}).classList.add("{}");
""".format(
js_selector, klass
)
)
)
js_selector_javascript = "() => {" + "\n".join(js_blocks) + "}"
print(js_selector_javascript, extra_selectors)
return js_selector_javascript, extra_selectors


def _selector_javascript(selectors, padding=0):
selector_to_shoot = "shot-scraper-{}".format(secrets.token_hex(8))
selector_javascript = textwrap.dedent(
Expand Down

0 comments on commit 8a61c7e

Please sign in to comment.