Skip to content

Commit 9fea0e8

Browse files
committed
feat: add clipping option for screenshots and implement element capture
1 parent 41f08ef commit 9fea0e8

File tree

2 files changed

+33
-3
lines changed

2 files changed

+33
-3
lines changed

pydoll/commands/page.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ def set_download_path(cls, path: str) -> dict:
5050
return command
5151

5252
@classmethod
53-
def screenshot(cls, format: str = 'png', quality: int = 100) -> dict:
53+
def screenshot(
54+
cls, format: str = 'png', quality: int = 100, clip: dict = None
55+
) -> dict:
5456
"""
5557
Generates the command to capture a screenshot of the current page.
5658
@@ -69,6 +71,8 @@ def screenshot(cls, format: str = 'png', quality: int = 100) -> dict:
6971
command = cls.SCREENSHOT_TEMPLATE.copy()
7072
command['params']['format'] = format
7173
command['params']['quality'] = quality
74+
if clip:
75+
command['params']['clip'] = clip
7276
return command
7377

7478
@classmethod

pydoll/element.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import asyncio
22
import json
33

4+
import aiofiles
45
from bs4 import BeautifulSoup
56

67
from pydoll import exceptions
78
from pydoll.commands.dom import DomCommands
89
from pydoll.commands.input import InputCommands
10+
from pydoll.commands.page import PageCommands
911
from pydoll.commands.runtime import RuntimeCommands
1012
from pydoll.connection import ConnectionHandler
1113
from pydoll.constants import Scripts
1214
from pydoll.mixins.find_elements import FindElementsMixin
15+
from pydoll.utils import decode_image_to_bytes
1316

1417

1518
class WebElement(FindElementsMixin):
@@ -125,7 +128,7 @@ async def get_bounds_using_js(self) -> list:
125128
response = await self._execute_script(
126129
Scripts.BOUNDS, return_by_value=True
127130
)
128-
return response['result']['result']['value']
131+
return json.loads(response['result']['result']['value'])
129132

130133
async def _execute_script(
131134
self, script: str, return_by_value: bool = False
@@ -170,6 +173,30 @@ async def _is_element_on_top(self):
170173
)
171174
return result['result']['result']['value']
172175

176+
async def get_screenshot(self, path: str):
177+
"""
178+
Takes a screenshot of the element.
179+
180+
Args:
181+
path (str): The path where the screenshot will be saved.
182+
"""
183+
bounds = await self.get_bounds_using_js()
184+
clip = {
185+
'x': bounds['x'],
186+
'y': bounds['y'],
187+
'width': bounds['width'],
188+
'height': bounds['height'],
189+
'scale': 1,
190+
}
191+
screenshot = await self._connection_handler.execute_command(
192+
PageCommands.screenshot(
193+
format='png', clip=clip
194+
)
195+
)
196+
async with aiofiles.open(path, 'wb') as file:
197+
image_bytes = decode_image_to_bytes(screenshot['result']['data'])
198+
await file.write(image_bytes)
199+
173200
async def get_element_text(self) -> str:
174201
"""
175202
Retrieves the text of the element.
@@ -241,7 +268,6 @@ async def click(self, x_offset: int = 0, y_offset: int = 0):
241268
)
242269
except KeyError:
243270
element_bounds = await self.get_bounds_using_js()
244-
element_bounds = json.loads(element_bounds)
245271
position_to_click = (
246272
element_bounds['x'] + element_bounds['width'] / 2,
247273
element_bounds['y'] + element_bounds['height'] / 2,

0 commit comments

Comments
 (0)