pydoll-python 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pydoll/__init__.py +0 -0
- pydoll/browser/__init__.py +0 -0
- pydoll/browser/base.py +524 -0
- pydoll/browser/chrome.py +31 -0
- pydoll/browser/managers.py +154 -0
- pydoll/browser/options.py +62 -0
- pydoll/browser/page.py +433 -0
- pydoll/commands/__init__.py +18 -0
- pydoll/commands/browser.py +108 -0
- pydoll/commands/dom.py +212 -0
- pydoll/commands/fetch.py +308 -0
- pydoll/commands/input.py +106 -0
- pydoll/commands/network.py +334 -0
- pydoll/commands/page.py +187 -0
- pydoll/commands/runtime.py +45 -0
- pydoll/commands/storage.py +18 -0
- pydoll/commands/target.py +35 -0
- pydoll/connection/__init__.py +0 -0
- pydoll/connection/connection.py +232 -0
- pydoll/connection/managers.py +136 -0
- pydoll/constants.py +125 -0
- pydoll/element.py +313 -0
- pydoll/events/__init__.py +13 -0
- pydoll/events/browser.py +26 -0
- pydoll/events/dom.py +108 -0
- pydoll/events/fetch.py +29 -0
- pydoll/events/network.py +160 -0
- pydoll/events/page.py +144 -0
- pydoll/exceptions.py +82 -0
- pydoll/mixins/__init__.py +0 -0
- pydoll/mixins/find_elements.py +180 -0
- pydoll/utils.py +50 -0
- pydoll_python-1.2.0.dist-info/LICENSE +9 -0
- pydoll_python-1.2.0.dist-info/METADATA +200 -0
- pydoll_python-1.2.0.dist-info/RECORD +36 -0
- pydoll_python-1.2.0.dist-info/WHEEL +4 -0
pydoll/commands/input.py
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
class InputCommands:
|
|
2
|
+
"""
|
|
3
|
+
A class to define input commands for simulating user interactions
|
|
4
|
+
with the browser using the Chrome DevTools Protocol (CDP).
|
|
5
|
+
The commands allow for simulating mouse clicks and keyboard presses.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
CLICK_ELEMENT_TEMPLATE = {
|
|
9
|
+
'method': 'Input.dispatchMouseEvent',
|
|
10
|
+
'params': {},
|
|
11
|
+
}
|
|
12
|
+
KEY_PRESS_TEMPLATE = {'method': 'Input.dispatchKeyEvent', 'params': {}}
|
|
13
|
+
INSERT_TEXT_TEMPLATE = {'method': 'Input.insertText', 'params': {}}
|
|
14
|
+
|
|
15
|
+
@classmethod
|
|
16
|
+
def mouse_press(cls, x: int, y: int) -> dict:
|
|
17
|
+
"""
|
|
18
|
+
Generates the command to simulate pressing the mouse button on a
|
|
19
|
+
specific location.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
x (int): The x-coordinate of the mouse press.
|
|
23
|
+
y (int): The y-coordinate of the mouse press.
|
|
24
|
+
|
|
25
|
+
This command utilizes the CDP to simulate a mouse press event at
|
|
26
|
+
the specified coordinates.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
dict: The command to be sent to the browser.
|
|
30
|
+
"""
|
|
31
|
+
command = cls.CLICK_ELEMENT_TEMPLATE.copy()
|
|
32
|
+
command['params'] = {
|
|
33
|
+
'type': 'mousePressed',
|
|
34
|
+
'button': 'left',
|
|
35
|
+
'x': x,
|
|
36
|
+
'y': y,
|
|
37
|
+
'clickCount': 1,
|
|
38
|
+
'modifiers': 0,
|
|
39
|
+
}
|
|
40
|
+
return command
|
|
41
|
+
|
|
42
|
+
@classmethod
|
|
43
|
+
def mouse_release(cls, x: int, y: int) -> dict:
|
|
44
|
+
"""
|
|
45
|
+
Generates the command to simulate releasing the mouse button.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
x (int): The x-coordinate of the mouse release.
|
|
49
|
+
y (int): The y-coordinate of the mouse release.
|
|
50
|
+
|
|
51
|
+
This command uses the CDP to simulate a mouse release event at
|
|
52
|
+
the specified coordinates.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
dict: The command to be sent to the browser.
|
|
56
|
+
"""
|
|
57
|
+
command = cls.CLICK_ELEMENT_TEMPLATE.copy()
|
|
58
|
+
command['params'] = {
|
|
59
|
+
'type': 'mouseReleased',
|
|
60
|
+
'button': 'left',
|
|
61
|
+
'x': x,
|
|
62
|
+
'y': y,
|
|
63
|
+
'clickCount': 1,
|
|
64
|
+
'modifiers': 0,
|
|
65
|
+
}
|
|
66
|
+
return command
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def key_press(cls, char: str) -> dict:
|
|
70
|
+
"""
|
|
71
|
+
Generates the command to simulate pressing a key on the keyboard.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
char (str): The character to be pressed.
|
|
75
|
+
|
|
76
|
+
This command utilizes the CDP to simulate a keyboard event for
|
|
77
|
+
the specified character.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
dict: The command to be sent to the browser.
|
|
81
|
+
"""
|
|
82
|
+
command = cls.KEY_PRESS_TEMPLATE.copy()
|
|
83
|
+
command['params'] = {
|
|
84
|
+
'type': 'char',
|
|
85
|
+
'text': char,
|
|
86
|
+
}
|
|
87
|
+
return command
|
|
88
|
+
|
|
89
|
+
@classmethod
|
|
90
|
+
def insert_text(cls, text: str) -> dict:
|
|
91
|
+
"""
|
|
92
|
+
Generates the command to insert text into an input field.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
text (str): The text to be inserted.
|
|
96
|
+
|
|
97
|
+
This command uses the CDP to simulate typing text into an input field.
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
dict: The command to be sent to the browser.
|
|
101
|
+
"""
|
|
102
|
+
command = cls.INSERT_TEXT_TEMPLATE.copy()
|
|
103
|
+
command['params'] = {
|
|
104
|
+
'text': text,
|
|
105
|
+
}
|
|
106
|
+
return command
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class NetworkCommands:
|
|
5
|
+
"""
|
|
6
|
+
This class encapsulates the network commands of the
|
|
7
|
+
Chrome DevTools Protocol (CDP).
|
|
8
|
+
|
|
9
|
+
CDP allows developers to interact with the Chrome browser's internal
|
|
10
|
+
mechanisms to inspect, manipulate, and monitor network operations,
|
|
11
|
+
which can be invaluable for debugging web applications, testing network
|
|
12
|
+
behaviors, and optimizing performance.
|
|
13
|
+
|
|
14
|
+
The commands defined in this class provide functionality for:
|
|
15
|
+
- Managing browser cache and cookies.
|
|
16
|
+
- Enabling and disabling network events.
|
|
17
|
+
- Retrieving and modifying request and response data.
|
|
18
|
+
- Customizing HTTP headers and user agent strings.
|
|
19
|
+
- Blocking specific URLs to prevent unwanted network traffic.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
CLEAR_BROWSER_CACHE = {'method': 'Network.clearBrowserCache'}
|
|
23
|
+
CLEAR_BROWSER_COOKIES = {'method': 'Network.clearBrowserCookies'}
|
|
24
|
+
DELETE_COOKIES_TEMPLATE = {'method': 'Network.deleteCookies', 'params': {}}
|
|
25
|
+
DISABLE = {'method': 'Network.disable'}
|
|
26
|
+
ENABLE = {'method': 'Network.enable'}
|
|
27
|
+
GET_COOKIES_TEMPLATE = {'method': 'Network.getCookies', 'params': {}}
|
|
28
|
+
GET_REQUEST_POST_DATA_TEMPLATE = {
|
|
29
|
+
'method': 'Network.getRequestPostData',
|
|
30
|
+
'params': {},
|
|
31
|
+
}
|
|
32
|
+
GET_RESPONSE_BODY_TEMPLATE = {
|
|
33
|
+
'method': 'Network.getResponseBody',
|
|
34
|
+
'params': {},
|
|
35
|
+
}
|
|
36
|
+
SET_CACHE_DISABLED_TEMPLATE = {
|
|
37
|
+
'method': 'Network.setCacheDisabled',
|
|
38
|
+
'params': {},
|
|
39
|
+
}
|
|
40
|
+
SET_COOKIE_TEMPLATE = {'method': 'Network.setCookie', 'params': {}}
|
|
41
|
+
SET_COOKIES_TEMPLATE = {'method': 'Network.setCookies', 'params': {}}
|
|
42
|
+
SET_EXTRA_HTTP_HEADERS_TEMPLATE = {
|
|
43
|
+
'method': 'Network.setExtraHTTPHeaders',
|
|
44
|
+
'params': {},
|
|
45
|
+
}
|
|
46
|
+
SET_USERAGENT_OVERRIDE_TEMPLATE = {
|
|
47
|
+
'method': 'Network.setUserAgentOverride',
|
|
48
|
+
'params': {},
|
|
49
|
+
}
|
|
50
|
+
GET_ALL_COOKIES = {'method': 'Network.getAllCookies'}
|
|
51
|
+
SEARCH_IN_RESPONSE_TEMPLATE = {
|
|
52
|
+
'method': 'Network.searchInResponseBody',
|
|
53
|
+
'params': {},
|
|
54
|
+
}
|
|
55
|
+
SET_BLOCKED_URLS = {'method': 'Network.setBlockedURLs', 'params': {}}
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def clear_browser_cache(cls):
|
|
59
|
+
"""
|
|
60
|
+
Command to clear the browser's cache.
|
|
61
|
+
|
|
62
|
+
This is useful when you want to ensure that your application retrieves
|
|
63
|
+
the most up-to-date resources from the server instead of loading
|
|
64
|
+
potentially stale data from the cache.
|
|
65
|
+
"""
|
|
66
|
+
return cls.CLEAR_BROWSER_CACHE
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def clear_browser_cookies(cls):
|
|
70
|
+
"""
|
|
71
|
+
Command to clear all cookies stored in the browser.
|
|
72
|
+
|
|
73
|
+
This can be beneficial for testing scenarios where you need
|
|
74
|
+
to simulate a fresh user session without any previously stored
|
|
75
|
+
cookies that might affect the application's behavior.
|
|
76
|
+
"""
|
|
77
|
+
return cls.CLEAR_BROWSER_COOKIES
|
|
78
|
+
|
|
79
|
+
@classmethod
|
|
80
|
+
def delete_cookies(cls, name: str, url: str = ''):
|
|
81
|
+
"""
|
|
82
|
+
Creates a command to delete a specific cookie by name.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
name (str): The name of the cookie to delete.
|
|
86
|
+
url (str, optional): The URL associated with the cookie.
|
|
87
|
+
If specified, only the cookie matching both the name and
|
|
88
|
+
URL will be deleted. If omitted, all cookies with the given
|
|
89
|
+
name will be deleted regardless of URL.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
dict: A command to delete the specified cookie.
|
|
93
|
+
"""
|
|
94
|
+
delete_cookies_template = copy.deepcopy(cls.DELETE_COOKIES_TEMPLATE)
|
|
95
|
+
delete_cookies_template['params']['name'] = name
|
|
96
|
+
if url:
|
|
97
|
+
delete_cookies_template['params']['url'] = url
|
|
98
|
+
return delete_cookies_template
|
|
99
|
+
|
|
100
|
+
@classmethod
|
|
101
|
+
def disable_network_events(cls):
|
|
102
|
+
"""
|
|
103
|
+
Command to disable network event notifications.
|
|
104
|
+
|
|
105
|
+
Use this command when you want to temporarily suspend the emission of
|
|
106
|
+
network events, which can be useful during specific operations
|
|
107
|
+
where you don't want to be notified about every network request
|
|
108
|
+
and response.
|
|
109
|
+
"""
|
|
110
|
+
return cls.DISABLE
|
|
111
|
+
|
|
112
|
+
@classmethod
|
|
113
|
+
def enable_network_events(cls):
|
|
114
|
+
"""
|
|
115
|
+
Command to enable network event notifications.
|
|
116
|
+
|
|
117
|
+
This allows you to start receiving network-related events again after
|
|
118
|
+
they have been disabled. It's essential to call this before you expect
|
|
119
|
+
to receive network events.
|
|
120
|
+
"""
|
|
121
|
+
return cls.ENABLE
|
|
122
|
+
|
|
123
|
+
@classmethod
|
|
124
|
+
def get_cookies(cls, urls: list[str] = []):
|
|
125
|
+
"""
|
|
126
|
+
Creates a command to retrieve cookies from specified URLs.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
urls (list[str], optional): A list of URLs for which to retrieve
|
|
130
|
+
cookies. If not provided, cookies from all URLs will
|
|
131
|
+
be fetched.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
dict: A command to get cookies associated with the specified URLs.
|
|
135
|
+
"""
|
|
136
|
+
get_cookies_template = copy.deepcopy(cls.GET_COOKIES_TEMPLATE)
|
|
137
|
+
if urls:
|
|
138
|
+
get_cookies_template['params']['urls'] = urls
|
|
139
|
+
return get_cookies_template
|
|
140
|
+
|
|
141
|
+
@classmethod
|
|
142
|
+
def get_request_post_data(cls, request_id: str):
|
|
143
|
+
"""
|
|
144
|
+
Creates a command to retrieve POST data associated with a specific
|
|
145
|
+
request.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
request_id (str): The unique identifier of the network
|
|
149
|
+
request whose POST data is to be retrieved.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
dict: A command to get the POST data for the specified request.
|
|
153
|
+
"""
|
|
154
|
+
get_request_post_data_template = copy.deepcopy(
|
|
155
|
+
cls.GET_REQUEST_POST_DATA_TEMPLATE
|
|
156
|
+
)
|
|
157
|
+
get_request_post_data_template['params']['requestId'] = request_id
|
|
158
|
+
return get_request_post_data_template
|
|
159
|
+
|
|
160
|
+
@classmethod
|
|
161
|
+
def get_response_body(cls, request_id: str):
|
|
162
|
+
"""
|
|
163
|
+
Creates a command to retrieve the body of a response for a specific
|
|
164
|
+
request.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
request_id (str): The unique identifier of the request
|
|
168
|
+
for which the response body is to be fetched.
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
dict: A command to get the response body associated with the
|
|
172
|
+
specified request.
|
|
173
|
+
"""
|
|
174
|
+
get_response_body_template = copy.deepcopy(
|
|
175
|
+
cls.GET_RESPONSE_BODY_TEMPLATE
|
|
176
|
+
)
|
|
177
|
+
get_response_body_template['params']['requestId'] = request_id
|
|
178
|
+
return get_response_body_template
|
|
179
|
+
|
|
180
|
+
@classmethod
|
|
181
|
+
def set_cache_disabled(cls, cache_disabled: bool):
|
|
182
|
+
"""
|
|
183
|
+
Creates a command to enable or disable the browser cache.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
cache_disabled (bool): Set to True to disable caching, or False to
|
|
187
|
+
enable it.
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
dict: A command to set the cache state in the browser.
|
|
191
|
+
"""
|
|
192
|
+
set_cache_disabled_template = copy.deepcopy(
|
|
193
|
+
cls.SET_CACHE_DISABLED_TEMPLATE
|
|
194
|
+
)
|
|
195
|
+
set_cache_disabled_template['params']['cacheDisabled'] = cache_disabled
|
|
196
|
+
return set_cache_disabled_template
|
|
197
|
+
|
|
198
|
+
@classmethod
|
|
199
|
+
def set_cookie(cls, name: str, value: str, url: str = ''):
|
|
200
|
+
"""
|
|
201
|
+
Creates a command to set a specific cookie.
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
name (str): The name of the cookie.
|
|
205
|
+
value (str): The value of the cookie.
|
|
206
|
+
url (str, optional): The URL associated with the cookie.
|
|
207
|
+
If provided, the cookie will be valid for this URL only.
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
dict: A command to set the specified cookie in the browser.
|
|
211
|
+
"""
|
|
212
|
+
set_cookie_template = copy.deepcopy(cls.SET_COOKIE_TEMPLATE)
|
|
213
|
+
set_cookie_template['params']['name'] = name
|
|
214
|
+
set_cookie_template['params']['value'] = value
|
|
215
|
+
if url:
|
|
216
|
+
set_cookie_template['params']['url'] = url
|
|
217
|
+
return set_cookie_template
|
|
218
|
+
|
|
219
|
+
@classmethod
|
|
220
|
+
def set_cookies(cls, cookies: list[dict]):
|
|
221
|
+
"""
|
|
222
|
+
Creates a command to set multiple cookies at once.
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
cookies (list[dict]): A list of dictionaries, each representing a
|
|
226
|
+
cookie with its properties (name, value, url, etc.).
|
|
227
|
+
|
|
228
|
+
Returns:
|
|
229
|
+
dict: A command to set the specified cookies in the browser.
|
|
230
|
+
"""
|
|
231
|
+
set_cookies_template = copy.deepcopy(cls.SET_COOKIES_TEMPLATE)
|
|
232
|
+
set_cookies_template['params']['cookies'] = cookies
|
|
233
|
+
return set_cookies_template
|
|
234
|
+
|
|
235
|
+
@classmethod
|
|
236
|
+
def set_extra_http_headers(cls, headers: dict):
|
|
237
|
+
"""
|
|
238
|
+
Creates a command to set additional HTTP headers for subsequent network
|
|
239
|
+
requests.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
headers (dict): A dictionary of headers to include in all future
|
|
243
|
+
requests.
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
dict: A command to set extra HTTP headers for the browser's network
|
|
247
|
+
requests.
|
|
248
|
+
"""
|
|
249
|
+
set_extra_http_headers_template = copy.deepcopy(
|
|
250
|
+
cls.SET_EXTRA_HTTP_HEADERS_TEMPLATE
|
|
251
|
+
)
|
|
252
|
+
set_extra_http_headers_template['params']['headers'] = headers
|
|
253
|
+
return set_extra_http_headers_template
|
|
254
|
+
|
|
255
|
+
@classmethod
|
|
256
|
+
def set_useragent_override(cls, user_agent: str):
|
|
257
|
+
"""
|
|
258
|
+
Creates a command to override the user agent string used in network
|
|
259
|
+
requests.
|
|
260
|
+
|
|
261
|
+
Args:
|
|
262
|
+
user_agent (str): The user agent string to set for future network
|
|
263
|
+
requests.
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
dict: A command to override the browser's user agent for network
|
|
267
|
+
requests.
|
|
268
|
+
"""
|
|
269
|
+
set_useragent_override_template = copy.deepcopy(
|
|
270
|
+
cls.SET_USERAGENT_OVERRIDE_TEMPLATE
|
|
271
|
+
)
|
|
272
|
+
set_useragent_override_template['params']['userAgent'] = user_agent
|
|
273
|
+
return set_useragent_override_template
|
|
274
|
+
|
|
275
|
+
@classmethod
|
|
276
|
+
def get_all_cookies(cls):
|
|
277
|
+
"""
|
|
278
|
+
Command to retrieve all cookies stored in the browser.
|
|
279
|
+
|
|
280
|
+
This can be useful for diagnostics, testing, or ensuring that your
|
|
281
|
+
application behaves as expected when accessing cookies.
|
|
282
|
+
"""
|
|
283
|
+
return cls.GET_ALL_COOKIES
|
|
284
|
+
|
|
285
|
+
@classmethod
|
|
286
|
+
def search_in_response(
|
|
287
|
+
cls,
|
|
288
|
+
request_id: str,
|
|
289
|
+
query: str,
|
|
290
|
+
case_sensitive: bool = False,
|
|
291
|
+
is_regex: bool = False,
|
|
292
|
+
):
|
|
293
|
+
"""
|
|
294
|
+
Creates a command to search for a specific query in the response body
|
|
295
|
+
of a network request.
|
|
296
|
+
|
|
297
|
+
Args:
|
|
298
|
+
request_id (str): The unique identifier of the request to search
|
|
299
|
+
within.
|
|
300
|
+
query (str): The string to search for within the response body.
|
|
301
|
+
case_sensitive (bool, optional): Whether the search should be case
|
|
302
|
+
sensitive. Defaults to False.
|
|
303
|
+
is_regex (bool, optional): Whether the query should be treated as a
|
|
304
|
+
regular expression. Defaults to False.
|
|
305
|
+
|
|
306
|
+
Returns:
|
|
307
|
+
dict: A command to search the specified query within the response
|
|
308
|
+
body of the given request.
|
|
309
|
+
"""
|
|
310
|
+
search_in_response_template = copy.deepcopy(
|
|
311
|
+
cls.SEARCH_IN_RESPONSE_TEMPLATE
|
|
312
|
+
)
|
|
313
|
+
search_in_response_template['params']['requestId'] = request_id
|
|
314
|
+
search_in_response_template['params']['query'] = query
|
|
315
|
+
search_in_response_template['params']['caseSensitive'] = case_sensitive
|
|
316
|
+
search_in_response_template['params']['isRegex'] = is_regex
|
|
317
|
+
return search_in_response_template
|
|
318
|
+
|
|
319
|
+
@classmethod
|
|
320
|
+
def set_blocked_urls(cls, urls: list[str]):
|
|
321
|
+
"""
|
|
322
|
+
Creates a command to block specific URLs from being requested by the
|
|
323
|
+
browser.
|
|
324
|
+
|
|
325
|
+
Args:
|
|
326
|
+
urls (list[str]): A list of URL patterns to block. The browser will
|
|
327
|
+
not make requests to any URLs matching these patterns.
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
dict: A command to set the specified URLs as blocked.
|
|
331
|
+
"""
|
|
332
|
+
set_blocked_urls_template = copy.deepcopy(cls.SET_BLOCKED_URLS)
|
|
333
|
+
set_blocked_urls_template['params']['urls'] = urls
|
|
334
|
+
return set_blocked_urls_template
|
pydoll/commands/page.py
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
class PageCommands:
|
|
2
|
+
"""
|
|
3
|
+
PageCommands class provides a set of commands to interact with the
|
|
4
|
+
Page domain of the Chrome DevTools Protocol (CDP). These commands enable
|
|
5
|
+
users to perform operations related to web pages, such as capturing
|
|
6
|
+
screenshots, navigating to URLs, refreshing pages, printing to PDF,
|
|
7
|
+
and enabling the Page domain.
|
|
8
|
+
|
|
9
|
+
The following operations can be performed:
|
|
10
|
+
- Capture a screenshot of the current page.
|
|
11
|
+
- Navigate to a specified URL.
|
|
12
|
+
- Refresh the current page, with an option to ignore the cache.
|
|
13
|
+
- Print the current page to a PDF document.
|
|
14
|
+
- Enable the Page domain for further interactions.
|
|
15
|
+
|
|
16
|
+
Each method generates a command that can be sent to the browser as part of
|
|
17
|
+
the DevTools Protocol communication.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
SCREENSHOT_TEMPLATE = {
|
|
21
|
+
'method': 'Page.captureScreenshot',
|
|
22
|
+
'params': {},
|
|
23
|
+
}
|
|
24
|
+
GO_TO_TEMPLATE = {'method': 'Page.navigate', 'params': {}}
|
|
25
|
+
REFRESH_TEMPLATE = {'method': 'Page.reload', 'params': {}}
|
|
26
|
+
PRINT_TO_PDF_TEMPLATE = {'method': 'Page.printToPDF', 'params': {}}
|
|
27
|
+
ENABLE_PAGE = {'method': 'Page.enable'}
|
|
28
|
+
DISABLE_PAGE = {'method': 'Page.disable'}
|
|
29
|
+
SET_DOWNLOAD_BEHAVIOR = {
|
|
30
|
+
'method': 'Page.setDownloadBehavior',
|
|
31
|
+
'params': {},
|
|
32
|
+
}
|
|
33
|
+
HANDLE_DIALOG = {'method': 'Page.handleJavaScriptDialog', 'params': {}}
|
|
34
|
+
CLOSE = {'method': 'Page.close'}
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def handle_dialog(cls, accept: bool = True) -> dict:
|
|
38
|
+
"""
|
|
39
|
+
Generates the command to handle a JavaScript dialog.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
accept (bool): Whether to accept the dialog.
|
|
43
|
+
If True, the dialog will be accepted.
|
|
44
|
+
If False, the dialog will be dismissed.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
dict: The command to be sent to the browser,
|
|
48
|
+
containing the method and parameters for handling the dialog.
|
|
49
|
+
"""
|
|
50
|
+
command = cls.HANDLE_DIALOG.copy()
|
|
51
|
+
command['params']['accept'] = accept
|
|
52
|
+
return command
|
|
53
|
+
|
|
54
|
+
@classmethod
|
|
55
|
+
def set_download_path(cls, path: str) -> dict:
|
|
56
|
+
"""
|
|
57
|
+
Generates the command to set the download path for the browser.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
path (str): The path where the downloaded files should be saved.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
dict: The command to be sent to the browser,
|
|
64
|
+
containing the method and parameters for setting
|
|
65
|
+
the download path.
|
|
66
|
+
"""
|
|
67
|
+
command = cls.SET_DOWNLOAD_BEHAVIOR.copy()
|
|
68
|
+
command['params']['behavior'] = 'allow'
|
|
69
|
+
command['params']['downloadPath'] = path
|
|
70
|
+
return command
|
|
71
|
+
|
|
72
|
+
@classmethod
|
|
73
|
+
def screenshot(
|
|
74
|
+
cls, format: str = 'jpeg', quality: int = 100, clip: dict = None
|
|
75
|
+
) -> dict:
|
|
76
|
+
"""
|
|
77
|
+
Generates the command to capture a screenshot of the current page.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
format (str): The format of the image to be captured.
|
|
81
|
+
Can be 'png' or 'jpeg'.
|
|
82
|
+
quality (int): The quality of the image to be captured,
|
|
83
|
+
applicable only if the format is 'jpeg'.
|
|
84
|
+
Value should be between 0 (lowest quality)
|
|
85
|
+
and 100 (highest quality).
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
dict: The command to be sent to the browser,
|
|
89
|
+
containing the method and parameters for the screenshot.
|
|
90
|
+
"""
|
|
91
|
+
command = cls.SCREENSHOT_TEMPLATE.copy()
|
|
92
|
+
command['params']['format'] = format
|
|
93
|
+
command['params']['quality'] = quality
|
|
94
|
+
if clip:
|
|
95
|
+
command['params']['clip'] = clip
|
|
96
|
+
return command
|
|
97
|
+
|
|
98
|
+
@classmethod
|
|
99
|
+
def go_to(cls, url: str) -> dict:
|
|
100
|
+
"""
|
|
101
|
+
Generates the command to navigate to a specific URL.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
url (str): The URL to navigate to. It should be a valid URL format.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
dict: The command to be sent to the browser,
|
|
108
|
+
containing the method and parameters for navigation.
|
|
109
|
+
"""
|
|
110
|
+
command = cls.GO_TO_TEMPLATE.copy()
|
|
111
|
+
command['params']['url'] = url
|
|
112
|
+
return command
|
|
113
|
+
|
|
114
|
+
@classmethod
|
|
115
|
+
def refresh(cls, ignore_cache: bool = False) -> dict:
|
|
116
|
+
"""
|
|
117
|
+
Generates the command to refresh the current page.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
ignore_cache (bool): Whether to ignore the cache when refreshing.
|
|
121
|
+
If True, the cached resources will not be
|
|
122
|
+
used.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
dict: The command to be sent to the browser,
|
|
126
|
+
containing the method and parameters for page refresh.
|
|
127
|
+
"""
|
|
128
|
+
command = cls.REFRESH_TEMPLATE.copy()
|
|
129
|
+
command['params']['ignoreCache'] = ignore_cache
|
|
130
|
+
return command
|
|
131
|
+
|
|
132
|
+
@classmethod
|
|
133
|
+
def print_to_pdf(
|
|
134
|
+
cls, scale: int = 1, paper_width: float = 8.5, paper_height: float = 11
|
|
135
|
+
) -> dict:
|
|
136
|
+
"""
|
|
137
|
+
Generates the command to print the current page to a PDF.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
scale (int): The scale of the page to print. Default is 1 (100%).
|
|
141
|
+
paper_width (float): The width of the paper to print on, in inches.
|
|
142
|
+
Default is 8.5 inches.
|
|
143
|
+
paper_height (float): The height of the paper to print on,
|
|
144
|
+
in inches. Default is 11 inches.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
dict: The command to be sent to the browser,
|
|
148
|
+
containing the method and parameters for printing to PDF.
|
|
149
|
+
"""
|
|
150
|
+
command = cls.PRINT_TO_PDF_TEMPLATE.copy()
|
|
151
|
+
command['params']['scale'] = scale
|
|
152
|
+
command['params']['paperWidth'] = paper_width
|
|
153
|
+
command['params']['paperHeight'] = paper_height
|
|
154
|
+
return command
|
|
155
|
+
|
|
156
|
+
@classmethod
|
|
157
|
+
def enable_page(cls) -> dict:
|
|
158
|
+
"""
|
|
159
|
+
Generates the command to enable the Page domain.
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
dict: The command to be sent to the browser,
|
|
163
|
+
containing the method to enable the Page domain.
|
|
164
|
+
"""
|
|
165
|
+
return cls.ENABLE_PAGE
|
|
166
|
+
|
|
167
|
+
@classmethod
|
|
168
|
+
def disable_page(cls) -> dict:
|
|
169
|
+
"""
|
|
170
|
+
Generates the command to disable the Page domain.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
dict: The command to be sent to the browser,
|
|
174
|
+
containing the method to disable the Page domain.
|
|
175
|
+
"""
|
|
176
|
+
return cls.DISABLE_PAGE
|
|
177
|
+
|
|
178
|
+
@classmethod
|
|
179
|
+
def close(cls) -> dict:
|
|
180
|
+
"""
|
|
181
|
+
Generates the command to close the current page.
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
dict: The command to be sent to the browser,
|
|
185
|
+
containing the method to close the current page.
|
|
186
|
+
"""
|
|
187
|
+
return cls.CLOSE
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class RuntimeCommands:
|
|
5
|
+
EVALUATE_TEMPLATE = {'method': 'Runtime.evaluate', 'params': {}}
|
|
6
|
+
CALL_FUNCTION_ON_TEMPLATE = {
|
|
7
|
+
'method': 'Runtime.callFunctionOn',
|
|
8
|
+
'params': {},
|
|
9
|
+
}
|
|
10
|
+
GET_PROPERTIES = {
|
|
11
|
+
'method': 'Runtime.getProperties',
|
|
12
|
+
'params': {},
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@classmethod
|
|
16
|
+
def get_properties(cls, object_id: str) -> dict:
|
|
17
|
+
"""Generates the command to get the properties of a specific object."""
|
|
18
|
+
command = copy.deepcopy(cls.GET_PROPERTIES)
|
|
19
|
+
command['params']['objectId'] = object_id
|
|
20
|
+
command['params']['ownProperties'] = True
|
|
21
|
+
return command
|
|
22
|
+
|
|
23
|
+
@classmethod
|
|
24
|
+
def call_function_on(
|
|
25
|
+
cls,
|
|
26
|
+
object_id: str,
|
|
27
|
+
function_declaration: str,
|
|
28
|
+
return_by_value: bool = False,
|
|
29
|
+
) -> dict:
|
|
30
|
+
"""Generates the command to call a function on a specific object."""
|
|
31
|
+
command = copy.deepcopy(cls.CALL_FUNCTION_ON_TEMPLATE)
|
|
32
|
+
command['params']['objectId'] = object_id
|
|
33
|
+
command['params']['functionDeclaration'] = function_declaration
|
|
34
|
+
command['params']['returnByValue'] = return_by_value
|
|
35
|
+
return command
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def evaluate_script(cls, expression: str) -> dict:
|
|
39
|
+
"""Generates the command to evaluate JavaScript code."""
|
|
40
|
+
command = copy.deepcopy(cls.EVALUATE_TEMPLATE)
|
|
41
|
+
command['params'] = {
|
|
42
|
+
'expression': expression,
|
|
43
|
+
'returnByValue': False,
|
|
44
|
+
}
|
|
45
|
+
return command
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class StorageCommands:
|
|
2
|
+
CLEAR_COOKIES = {'method': 'Storage.clearCookies', 'params': {}}
|
|
3
|
+
SET_COOKIES = {'method': 'Storage.setCookies', 'params': {}}
|
|
4
|
+
GET_COOKIES = {'method': 'Storage.getCookies', 'params': {}}
|
|
5
|
+
|
|
6
|
+
@classmethod
|
|
7
|
+
def clear_cookies(cls) -> dict:
|
|
8
|
+
return cls.CLEAR_COOKIES
|
|
9
|
+
|
|
10
|
+
@classmethod
|
|
11
|
+
def set_cookies(cls, cookies: list) -> dict:
|
|
12
|
+
set_cookies = cls.SET_COOKIES.copy()
|
|
13
|
+
set_cookies['params']['cookies'] = cookies
|
|
14
|
+
return set_cookies
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def get_cookies(cls) -> dict:
|
|
18
|
+
return cls.GET_COOKIES
|