seleniumbase 4.24.11__py3-none-any.whl → 4.33.15__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- sbase/__init__.py +1 -0
- sbase/steps.py +7 -0
- seleniumbase/__init__.py +16 -7
- seleniumbase/__version__.py +1 -1
- seleniumbase/behave/behave_sb.py +97 -32
- seleniumbase/common/decorators.py +16 -7
- seleniumbase/config/proxy_list.py +3 -3
- seleniumbase/config/settings.py +4 -0
- seleniumbase/console_scripts/logo_helper.py +47 -8
- seleniumbase/console_scripts/run.py +345 -335
- seleniumbase/console_scripts/sb_behave_gui.py +5 -12
- seleniumbase/console_scripts/sb_caseplans.py +6 -13
- seleniumbase/console_scripts/sb_commander.py +5 -12
- seleniumbase/console_scripts/sb_install.py +62 -54
- seleniumbase/console_scripts/sb_mkchart.py +13 -20
- seleniumbase/console_scripts/sb_mkdir.py +11 -17
- seleniumbase/console_scripts/sb_mkfile.py +69 -43
- seleniumbase/console_scripts/sb_mkpres.py +13 -20
- seleniumbase/console_scripts/sb_mkrec.py +88 -21
- seleniumbase/console_scripts/sb_objectify.py +30 -30
- seleniumbase/console_scripts/sb_print.py +5 -12
- seleniumbase/console_scripts/sb_recorder.py +16 -11
- seleniumbase/core/browser_launcher.py +1658 -221
- seleniumbase/core/log_helper.py +42 -27
- seleniumbase/core/mysql.py +1 -4
- seleniumbase/core/proxy_helper.py +35 -30
- seleniumbase/core/recorder_helper.py +24 -5
- seleniumbase/core/sb_cdp.py +1951 -0
- seleniumbase/core/sb_driver.py +162 -8
- seleniumbase/core/settings_parser.py +6 -0
- seleniumbase/core/style_sheet.py +10 -0
- seleniumbase/extensions/recorder.zip +0 -0
- seleniumbase/fixtures/base_case.py +1225 -614
- seleniumbase/fixtures/constants.py +10 -1
- seleniumbase/fixtures/js_utils.py +171 -144
- seleniumbase/fixtures/page_actions.py +177 -13
- seleniumbase/fixtures/page_utils.py +25 -53
- seleniumbase/fixtures/shared_utils.py +97 -11
- seleniumbase/js_code/active_css_js.py +1 -1
- seleniumbase/js_code/recorder_js.py +1 -1
- seleniumbase/plugins/base_plugin.py +2 -3
- seleniumbase/plugins/driver_manager.py +340 -65
- seleniumbase/plugins/pytest_plugin.py +276 -47
- seleniumbase/plugins/sb_manager.py +412 -99
- seleniumbase/plugins/selenium_plugin.py +122 -17
- seleniumbase/translate/translator.py +0 -7
- seleniumbase/undetected/__init__.py +59 -52
- seleniumbase/undetected/cdp.py +0 -1
- seleniumbase/undetected/cdp_driver/__init__.py +1 -0
- seleniumbase/undetected/cdp_driver/_contradict.py +110 -0
- seleniumbase/undetected/cdp_driver/browser.py +829 -0
- seleniumbase/undetected/cdp_driver/cdp_util.py +458 -0
- seleniumbase/undetected/cdp_driver/config.py +334 -0
- seleniumbase/undetected/cdp_driver/connection.py +639 -0
- seleniumbase/undetected/cdp_driver/element.py +1168 -0
- seleniumbase/undetected/cdp_driver/tab.py +1323 -0
- seleniumbase/undetected/dprocess.py +4 -7
- seleniumbase/undetected/options.py +6 -8
- seleniumbase/undetected/patcher.py +11 -13
- seleniumbase/undetected/reactor.py +0 -1
- seleniumbase/undetected/webelement.py +16 -3
- {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/LICENSE +1 -1
- {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/METADATA +299 -252
- {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/RECORD +67 -69
- {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/WHEEL +1 -1
- sbase/ReadMe.txt +0 -2
- seleniumbase/ReadMe.md +0 -25
- seleniumbase/common/ReadMe.md +0 -71
- seleniumbase/console_scripts/ReadMe.md +0 -731
- seleniumbase/drivers/ReadMe.md +0 -27
- seleniumbase/extensions/ReadMe.md +0 -12
- seleniumbase/masterqa/ReadMe.md +0 -61
- seleniumbase/resources/ReadMe.md +0 -31
- seleniumbase/resources/favicon.ico +0 -0
- seleniumbase/utilities/selenium_grid/ReadMe.md +0 -84
- seleniumbase/utilities/selenium_ide/ReadMe.md +0 -111
- {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/entry_points.txt +0 -0
- {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/top_level.txt +0 -0
@@ -9,8 +9,11 @@ import time
|
|
9
9
|
import types
|
10
10
|
import urllib3
|
11
11
|
import warnings
|
12
|
+
from contextlib import suppress
|
12
13
|
from selenium import webdriver
|
13
14
|
from selenium.common.exceptions import ElementClickInterceptedException
|
15
|
+
from selenium.common.exceptions import InvalidSessionIdException
|
16
|
+
from selenium.common.exceptions import SessionNotCreatedException
|
14
17
|
from selenium.webdriver.chrome.service import Service as ChromeService
|
15
18
|
from selenium.webdriver.common.options import ArgOptions
|
16
19
|
from selenium.webdriver.common.service import utils as service_utils
|
@@ -26,7 +29,10 @@ from seleniumbase.core import detect_b_ver
|
|
26
29
|
from seleniumbase.core import download_helper
|
27
30
|
from seleniumbase.core import proxy_helper
|
28
31
|
from seleniumbase.core import sb_driver
|
32
|
+
from seleniumbase.core import sb_cdp
|
29
33
|
from seleniumbase.fixtures import constants
|
34
|
+
from seleniumbase.fixtures import js_utils
|
35
|
+
from seleniumbase.fixtures import page_actions
|
30
36
|
from seleniumbase.fixtures import shared_utils
|
31
37
|
|
32
38
|
urllib3.disable_warnings()
|
@@ -91,19 +97,12 @@ def log_d(message):
|
|
91
97
|
print(message)
|
92
98
|
|
93
99
|
|
94
|
-
def make_executable(file_path):
|
95
|
-
# Set permissions to: "If you can read it, you can execute it."
|
96
|
-
mode = os.stat(file_path).st_mode
|
97
|
-
mode |= (mode & 0o444) >> 2 # copy R bits to X
|
98
|
-
os.chmod(file_path, mode)
|
99
|
-
|
100
|
-
|
101
100
|
def make_driver_executable_if_not(driver_path):
|
102
101
|
# Verify driver has executable permissions. If not, add them.
|
103
102
|
permissions = oct(os.stat(driver_path)[0])[-3:]
|
104
103
|
if "4" in permissions or "6" in permissions:
|
105
104
|
# We want at least a '5' or '7' to make sure it's executable
|
106
|
-
make_executable(driver_path)
|
105
|
+
shared_utils.make_executable(driver_path)
|
107
106
|
|
108
107
|
|
109
108
|
def extend_driver(driver):
|
@@ -129,9 +128,13 @@ def extend_driver(driver):
|
|
129
128
|
page.assert_element_not_visible = DM.assert_element_not_visible
|
130
129
|
page.assert_text = DM.assert_text
|
131
130
|
page.assert_exact_text = DM.assert_exact_text
|
131
|
+
page.assert_non_empty_text = DM.assert_non_empty_text
|
132
|
+
page.assert_text_not_visible = DM.assert_text_not_visible
|
132
133
|
page.wait_for_element = DM.wait_for_element
|
133
134
|
page.wait_for_text = DM.wait_for_text
|
134
135
|
page.wait_for_exact_text = DM.wait_for_exact_text
|
136
|
+
page.wait_for_non_empty_text = DM.wait_for_non_empty_text
|
137
|
+
page.wait_for_text_not_visible = DM.wait_for_text_not_visible
|
135
138
|
page.wait_for_and_accept_alert = DM.wait_for_and_accept_alert
|
136
139
|
page.wait_for_and_dismiss_alert = DM.wait_for_and_dismiss_alert
|
137
140
|
page.is_element_present = DM.is_element_present
|
@@ -139,12 +142,22 @@ def extend_driver(driver):
|
|
139
142
|
page.is_text_visible = DM.is_text_visible
|
140
143
|
page.is_exact_text_visible = DM.is_exact_text_visible
|
141
144
|
page.is_attribute_present = DM.is_attribute_present
|
145
|
+
page.is_non_empty_text_visible = DM.is_non_empty_text_visible
|
142
146
|
page.get_text = DM.get_text
|
143
147
|
page.find_element = DM.find_element
|
144
148
|
page.find_elements = DM.find_elements
|
145
149
|
page.locator = DM.locator
|
150
|
+
page.get_current_url = DM.get_current_url
|
146
151
|
page.get_page_source = DM.get_page_source
|
147
152
|
page.get_title = DM.get_title
|
153
|
+
page.get_page_title = DM.get_title
|
154
|
+
page.switch_to_default_window = DM.switch_to_default_window
|
155
|
+
page.switch_to_newest_window = DM.switch_to_newest_window
|
156
|
+
page.open_new_window = DM.open_new_window
|
157
|
+
page.open_new_tab = DM.open_new_tab
|
158
|
+
page.switch_to_window = DM.switch_to_window
|
159
|
+
page.switch_to_tab = DM.switch_to_tab
|
160
|
+
page.switch_to_frame = DM.switch_to_frame
|
148
161
|
driver.page = page
|
149
162
|
js = types.SimpleNamespace()
|
150
163
|
js.js_click = DM.js_click
|
@@ -168,12 +181,16 @@ def extend_driver(driver):
|
|
168
181
|
driver.assert_element_not_visible = DM.assert_element_not_visible
|
169
182
|
driver.assert_text = DM.assert_text
|
170
183
|
driver.assert_exact_text = DM.assert_exact_text
|
184
|
+
driver.assert_non_empty_text = DM.assert_non_empty_text
|
185
|
+
driver.assert_text_not_visible = DM.assert_text_not_visible
|
171
186
|
driver.wait_for_element = DM.wait_for_element
|
172
187
|
driver.wait_for_element_visible = DM.wait_for_element_visible
|
173
188
|
driver.wait_for_element_present = DM.wait_for_element_present
|
174
189
|
driver.wait_for_selector = DM.wait_for_selector
|
175
190
|
driver.wait_for_text = DM.wait_for_text
|
176
191
|
driver.wait_for_exact_text = DM.wait_for_exact_text
|
192
|
+
driver.wait_for_non_empty_text = DM.wait_for_non_empty_text
|
193
|
+
driver.wait_for_text_not_visible = DM.wait_for_text_not_visible
|
177
194
|
driver.wait_for_and_accept_alert = DM.wait_for_and_accept_alert
|
178
195
|
driver.wait_for_and_dismiss_alert = DM.wait_for_and_dismiss_alert
|
179
196
|
driver.is_element_present = DM.is_element_present
|
@@ -181,20 +198,38 @@ def extend_driver(driver):
|
|
181
198
|
driver.is_text_visible = DM.is_text_visible
|
182
199
|
driver.is_exact_text_visible = DM.is_exact_text_visible
|
183
200
|
driver.is_attribute_present = DM.is_attribute_present
|
184
|
-
driver.
|
201
|
+
driver.is_non_empty_text_visible = DM.is_non_empty_text_visible
|
202
|
+
driver.is_valid_url = DM.is_valid_url
|
203
|
+
driver.is_alert_present = DM.is_alert_present
|
204
|
+
driver.is_online = DM.is_online
|
205
|
+
driver.is_connected = DM.is_connected
|
206
|
+
driver.is_uc_mode_active = DM.is_uc_mode_active
|
207
|
+
driver.is_cdp_mode_active = DM.is_cdp_mode_active
|
185
208
|
driver.js_click = DM.js_click
|
209
|
+
driver.get_text = DM.get_text
|
186
210
|
driver.get_active_element_css = DM.get_active_element_css
|
187
211
|
driver.get_locale_code = DM.get_locale_code
|
212
|
+
driver.get_screen_rect = DM.get_screen_rect
|
188
213
|
driver.get_origin = DM.get_origin
|
189
214
|
driver.get_user_agent = DM.get_user_agent
|
215
|
+
driver.get_cookie_string = DM.get_cookie_string
|
190
216
|
driver.highlight = DM.highlight
|
191
217
|
driver.highlight_click = DM.highlight_click
|
192
218
|
driver.highlight_if_visible = DM.highlight_if_visible
|
193
219
|
driver.sleep = time.sleep
|
194
220
|
driver.get_attribute = DM.get_attribute
|
221
|
+
driver.get_current_url = DM.get_current_url
|
195
222
|
driver.get_page_source = DM.get_page_source
|
196
223
|
driver.get_title = DM.get_title
|
224
|
+
driver.get_page_title = DM.get_title
|
225
|
+
driver.switch_to_default_window = DM.switch_to_default_window
|
226
|
+
driver.switch_to_newest_window = DM.switch_to_newest_window
|
227
|
+
driver.open_new_window = DM.open_new_window
|
228
|
+
driver.open_new_tab = DM.open_new_tab
|
229
|
+
driver.switch_to_window = DM.switch_to_window
|
230
|
+
driver.switch_to_tab = DM.switch_to_tab
|
197
231
|
driver.switch_to_frame = DM.switch_to_frame
|
232
|
+
driver.reset_window_size = DM.reset_window_size
|
198
233
|
if hasattr(driver, "proxy"):
|
199
234
|
driver.set_wire_proxy = DM.set_wire_proxy
|
200
235
|
return driver
|
@@ -249,7 +284,7 @@ def chromedriver_on_path():
|
|
249
284
|
def get_uc_driver_version(full=False):
|
250
285
|
uc_driver_version = None
|
251
286
|
if os.path.exists(LOCAL_UC_DRIVER):
|
252
|
-
|
287
|
+
with suppress(Exception):
|
253
288
|
output = subprocess.check_output(
|
254
289
|
'"%s" --version' % LOCAL_UC_DRIVER, shell=True
|
255
290
|
)
|
@@ -264,8 +299,6 @@ def get_uc_driver_version(full=False):
|
|
264
299
|
uc_driver_version = full_version
|
265
300
|
else:
|
266
301
|
uc_driver_version = output
|
267
|
-
except Exception:
|
268
|
-
pass
|
269
302
|
return uc_driver_version
|
270
303
|
|
271
304
|
|
@@ -312,17 +345,19 @@ def find_edgedriver_version_to_use(use_version, driver_version):
|
|
312
345
|
return use_version
|
313
346
|
|
314
347
|
|
315
|
-
def
|
348
|
+
def has_captcha(text):
|
316
349
|
if (
|
317
350
|
"<title>403 Forbidden</title>" in text
|
318
351
|
or "Permission Denied</title>" in text
|
319
352
|
or 'id="challenge-error-text"' in text
|
320
353
|
or "<title>Just a moment..." in text
|
321
354
|
or 'action="/?__cf_chl_f_tk' in text
|
355
|
+
or 'id="challenge-widget-' in text
|
322
356
|
or 'src="chromedriver.js"' in text
|
323
357
|
or 'class="g-recaptcha"' in text
|
324
358
|
or 'content="Pixelscan"' in text
|
325
359
|
or 'id="challenge-form"' in text
|
360
|
+
or "/challenge-platform" in text
|
326
361
|
or "window._cf_chl_opt" in text
|
327
362
|
or "/recaptcha/api.js" in text
|
328
363
|
or "/turnstile/" in text
|
@@ -331,6 +366,11 @@ def has_cf(text):
|
|
331
366
|
return False
|
332
367
|
|
333
368
|
|
369
|
+
def __is_cdp_swap_needed(driver):
|
370
|
+
"""If the driver is disconnected, use a CDP method when available."""
|
371
|
+
return shared_utils.is_cdp_swap_needed(driver)
|
372
|
+
|
373
|
+
|
334
374
|
def uc_special_open_if_cf(
|
335
375
|
driver,
|
336
376
|
url,
|
@@ -342,32 +382,32 @@ def uc_special_open_if_cf(
|
|
342
382
|
):
|
343
383
|
if url.startswith("http:") or url.startswith("https:"):
|
344
384
|
special = False
|
345
|
-
|
385
|
+
with suppress(Exception):
|
346
386
|
req_get = requests_get(url, proxy_string)
|
347
387
|
status_str = str(req_get.status_code)
|
348
388
|
if (
|
349
389
|
status_str.startswith("3")
|
350
390
|
or status_str.startswith("4")
|
351
391
|
or status_str.startswith("5")
|
352
|
-
or
|
392
|
+
or has_captcha(req_get.text)
|
353
393
|
):
|
354
394
|
special = True
|
355
395
|
if status_str == "403" or status_str == "429":
|
356
396
|
time.sleep(0.06) # Forbidden / Blocked! (Wait first!)
|
357
|
-
except Exception:
|
358
|
-
pass
|
359
397
|
if special:
|
360
398
|
time.sleep(0.05)
|
361
399
|
with driver:
|
362
400
|
driver.execute_script('window.open("%s","_blank");' % url)
|
363
401
|
driver.close()
|
364
402
|
if mobile_emulator:
|
365
|
-
|
403
|
+
page_actions.switch_to_window(
|
404
|
+
driver, driver.window_handles[-1], 2
|
405
|
+
)
|
366
406
|
uc_metrics = {}
|
367
407
|
if (
|
368
408
|
isinstance(device_width, int)
|
369
409
|
and isinstance(device_height, int)
|
370
|
-
and isinstance(device_pixel_ratio, int)
|
410
|
+
and isinstance(device_pixel_ratio, (int, float))
|
371
411
|
):
|
372
412
|
uc_metrics["width"] = device_width
|
373
413
|
uc_metrics["height"] = device_height
|
@@ -384,15 +424,15 @@ def uc_special_open_if_cf(
|
|
384
424
|
"mobile": True
|
385
425
|
}
|
386
426
|
)
|
387
|
-
|
427
|
+
with suppress(Exception):
|
388
428
|
driver.execute_cdp_cmd(
|
389
429
|
'Emulation.setDeviceMetricsOverride',
|
390
430
|
set_device_metrics_override
|
391
431
|
)
|
392
|
-
except Exception:
|
393
|
-
pass
|
394
432
|
if not mobile_emulator:
|
395
|
-
|
433
|
+
page_actions.switch_to_window(
|
434
|
+
driver, driver.window_handles[-1], 2
|
435
|
+
)
|
396
436
|
else:
|
397
437
|
driver.default_get(url) # The original one
|
398
438
|
else:
|
@@ -401,30 +441,31 @@ def uc_special_open_if_cf(
|
|
401
441
|
|
402
442
|
|
403
443
|
def uc_open(driver, url):
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
444
|
+
url = shared_utils.fix_url_as_needed(url)
|
445
|
+
if __is_cdp_swap_needed(driver):
|
446
|
+
driver.cdp.get(url)
|
447
|
+
time.sleep(0.3)
|
448
|
+
return
|
408
449
|
if (url.startswith("http:") or url.startswith("https:")):
|
409
|
-
time.sleep(0.05)
|
410
450
|
with driver:
|
411
|
-
|
451
|
+
script = 'window.location.href = "%s";' % url
|
452
|
+
js_utils.call_me_later(driver, script, 5)
|
412
453
|
else:
|
413
454
|
driver.default_get(url) # The original one
|
414
455
|
return None
|
415
456
|
|
416
457
|
|
417
458
|
def uc_open_with_tab(driver, url):
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
459
|
+
url = shared_utils.fix_url_as_needed(url)
|
460
|
+
if __is_cdp_swap_needed(driver):
|
461
|
+
driver.cdp.get(url)
|
462
|
+
time.sleep(0.3)
|
463
|
+
return
|
422
464
|
if (url.startswith("http:") or url.startswith("https:")):
|
423
|
-
time.sleep(0.05)
|
424
465
|
with driver:
|
425
466
|
driver.execute_script('window.open("%s","_blank");' % url)
|
426
467
|
driver.close()
|
427
|
-
|
468
|
+
page_actions.switch_to_window(driver, driver.window_handles[-1], 2)
|
428
469
|
else:
|
429
470
|
driver.default_get(url) # The original one
|
430
471
|
return None
|
@@ -432,17 +473,314 @@ def uc_open_with_tab(driver, url):
|
|
432
473
|
|
433
474
|
def uc_open_with_reconnect(driver, url, reconnect_time=None):
|
434
475
|
"""Open a url, disconnect chromedriver, wait, and reconnect."""
|
476
|
+
url = shared_utils.fix_url_as_needed(url)
|
477
|
+
if __is_cdp_swap_needed(driver):
|
478
|
+
driver.cdp.get(url)
|
479
|
+
time.sleep(0.3)
|
480
|
+
return
|
435
481
|
if not reconnect_time:
|
436
482
|
reconnect_time = constants.UC.RECONNECT_TIME
|
437
|
-
if url.startswith("//"):
|
438
|
-
url = "https:" + url
|
439
|
-
elif ":" not in url:
|
440
|
-
url = "https://" + url
|
441
483
|
if (url.startswith("http:") or url.startswith("https:")):
|
442
|
-
|
484
|
+
script = 'window.open("%s","_blank");' % url
|
485
|
+
driver.execute_script(script)
|
486
|
+
time.sleep(0.05)
|
487
|
+
driver.close()
|
488
|
+
if reconnect_time == "disconnect":
|
489
|
+
driver.disconnect()
|
490
|
+
time.sleep(0.008)
|
491
|
+
else:
|
492
|
+
driver.reconnect(reconnect_time)
|
493
|
+
time.sleep(0.004)
|
494
|
+
try:
|
495
|
+
page_actions.switch_to_window(
|
496
|
+
driver, driver.window_handles[-1], 2
|
497
|
+
)
|
498
|
+
except InvalidSessionIdException:
|
499
|
+
time.sleep(0.05)
|
500
|
+
page_actions.switch_to_window(
|
501
|
+
driver, driver.window_handles[-1], 2
|
502
|
+
)
|
503
|
+
else:
|
504
|
+
driver.default_get(url) # The original one
|
505
|
+
return None
|
506
|
+
|
507
|
+
|
508
|
+
def uc_open_with_cdp_mode(driver, url=None):
|
509
|
+
import asyncio
|
510
|
+
from seleniumbase.undetected.cdp_driver import cdp_util
|
511
|
+
|
512
|
+
current_url = None
|
513
|
+
try:
|
514
|
+
current_url = driver.current_url
|
515
|
+
except Exception:
|
516
|
+
driver.connect()
|
517
|
+
current_url = driver.current_url
|
518
|
+
url_protocol = current_url.split(":")[0]
|
519
|
+
if url_protocol not in ["about", "data", "chrome"]:
|
520
|
+
script = 'window.open("data:,","_blank");'
|
521
|
+
js_utils.call_me_later(driver, script, 3)
|
522
|
+
time.sleep(0.012)
|
523
|
+
driver.close()
|
524
|
+
driver.disconnect()
|
525
|
+
|
526
|
+
cdp_details = driver._get_cdp_details()
|
527
|
+
cdp_host = cdp_details[1].split("://")[1].split(":")[0]
|
528
|
+
cdp_port = int(cdp_details[1].split("://")[1].split(":")[1].split("/")[0])
|
529
|
+
|
530
|
+
url = shared_utils.fix_url_as_needed(url)
|
531
|
+
url_protocol = url.split(":")[0]
|
532
|
+
safe_url = True
|
533
|
+
if url_protocol not in ["about", "data", "chrome"]:
|
534
|
+
safe_url = False
|
535
|
+
|
536
|
+
headless = False
|
537
|
+
headed = None
|
538
|
+
xvfb = None
|
539
|
+
if hasattr(sb_config, "headless"):
|
540
|
+
headless = sb_config.headless
|
541
|
+
if hasattr(sb_config, "headed"):
|
542
|
+
headed = sb_config.headed
|
543
|
+
if hasattr(sb_config, "xvfb"):
|
544
|
+
xvfb = sb_config.xvfb
|
545
|
+
|
546
|
+
loop = asyncio.new_event_loop()
|
547
|
+
asyncio.set_event_loop(loop)
|
548
|
+
driver.cdp_base = loop.run_until_complete(
|
549
|
+
cdp_util.start(
|
550
|
+
host=cdp_host,
|
551
|
+
port=cdp_port,
|
552
|
+
headless=headless,
|
553
|
+
headed=headed,
|
554
|
+
xvfb=xvfb,
|
555
|
+
)
|
556
|
+
)
|
557
|
+
loop.run_until_complete(driver.cdp_base.wait(0))
|
558
|
+
|
559
|
+
gui_lock = fasteners.InterProcessLock(constants.MultiBrowser.PYAUTOGUILOCK)
|
560
|
+
|
561
|
+
if (
|
562
|
+
"chrome-extension://" in str(driver.cdp_base.main_tab)
|
563
|
+
and len(driver.cdp_base.tabs) >= 2
|
564
|
+
):
|
565
|
+
with suppress(Exception):
|
566
|
+
loop.run_until_complete(driver.cdp_base.main_tab.close())
|
567
|
+
|
568
|
+
for tab in driver.cdp_base.tabs[-1::-1]:
|
569
|
+
if "chrome-extension://" not in str(tab):
|
570
|
+
with gui_lock:
|
571
|
+
with suppress(Exception):
|
572
|
+
shared_utils.make_writable(
|
573
|
+
constants.MultiBrowser.PYAUTOGUILOCK
|
574
|
+
)
|
575
|
+
loop.run_until_complete(tab.activate())
|
576
|
+
break
|
577
|
+
|
578
|
+
page_tab = None
|
579
|
+
if "chrome-extension://" not in str(driver.cdp_base.tabs[-1]):
|
580
|
+
page_tab = driver.cdp_base.tabs[-1]
|
581
|
+
else:
|
582
|
+
for tab in driver.cdp_base.tabs:
|
583
|
+
if "chrome-extension://" not in str(tab):
|
584
|
+
page_tab = tab
|
585
|
+
break
|
586
|
+
if page_tab:
|
587
|
+
loop.run_until_complete(page_tab.aopen())
|
588
|
+
with gui_lock:
|
589
|
+
with suppress(Exception):
|
590
|
+
shared_utils.make_writable(
|
591
|
+
constants.MultiBrowser.PYAUTOGUILOCK
|
592
|
+
)
|
593
|
+
loop.run_until_complete(page_tab.activate())
|
594
|
+
|
595
|
+
loop.run_until_complete(driver.cdp_base.update_targets())
|
596
|
+
page = loop.run_until_complete(driver.cdp_base.get(url))
|
597
|
+
with gui_lock:
|
598
|
+
with suppress(Exception):
|
599
|
+
shared_utils.make_writable(constants.MultiBrowser.PYAUTOGUILOCK)
|
600
|
+
loop.run_until_complete(page.activate())
|
601
|
+
loop.run_until_complete(page.wait())
|
602
|
+
if not safe_url:
|
603
|
+
time.sleep(constants.UC.CDP_MODE_OPEN_WAIT)
|
604
|
+
if IS_WINDOWS:
|
605
|
+
time.sleep(constants.UC.EXTRA_WINDOWS_WAIT)
|
606
|
+
else:
|
607
|
+
time.sleep(0.012)
|
608
|
+
cdp = types.SimpleNamespace()
|
609
|
+
CDPM = sb_cdp.CDPMethods(loop, page, driver)
|
610
|
+
cdp.get = CDPM.get
|
611
|
+
cdp.open = CDPM.open
|
612
|
+
cdp.reload = CDPM.reload
|
613
|
+
cdp.refresh = CDPM.refresh
|
614
|
+
cdp.add_handler = CDPM.add_handler
|
615
|
+
cdp.get_event_loop = CDPM.get_event_loop
|
616
|
+
cdp.find_element = CDPM.find_element
|
617
|
+
cdp.find = CDPM.find_element
|
618
|
+
cdp.locator = CDPM.find_element
|
619
|
+
cdp.find_element_by_text = CDPM.find_element_by_text
|
620
|
+
cdp.find_all = CDPM.find_all
|
621
|
+
cdp.find_elements_by_text = CDPM.find_elements_by_text
|
622
|
+
cdp.select = CDPM.select
|
623
|
+
cdp.select_all = CDPM.select_all
|
624
|
+
cdp.find_elements = CDPM.find_elements
|
625
|
+
cdp.find_visible_elements = CDPM.find_visible_elements
|
626
|
+
cdp.click_nth_element = CDPM.click_nth_element
|
627
|
+
cdp.click_nth_visible_element = CDPM.click_nth_visible_element
|
628
|
+
cdp.click_link = CDPM.click_link
|
629
|
+
cdp.go_back = CDPM.go_back
|
630
|
+
cdp.go_forward = CDPM.go_forward
|
631
|
+
cdp.get_navigation_history = CDPM.get_navigation_history
|
632
|
+
cdp.tile_windows = CDPM.tile_windows
|
633
|
+
cdp.get_all_cookies = CDPM.get_all_cookies
|
634
|
+
cdp.set_all_cookies = CDPM.set_all_cookies
|
635
|
+
cdp.save_cookies = CDPM.save_cookies
|
636
|
+
cdp.load_cookies = CDPM.load_cookies
|
637
|
+
cdp.clear_cookies = CDPM.clear_cookies
|
638
|
+
cdp.sleep = CDPM.sleep
|
639
|
+
cdp.bring_active_window_to_front = CDPM.bring_active_window_to_front
|
640
|
+
cdp.bring_to_front = CDPM.bring_active_window_to_front
|
641
|
+
cdp.get_active_element = CDPM.get_active_element
|
642
|
+
cdp.get_active_element_css = CDPM.get_active_element_css
|
643
|
+
cdp.click = CDPM.click
|
644
|
+
cdp.click_active_element = CDPM.click_active_element
|
645
|
+
cdp.click_if_visible = CDPM.click_if_visible
|
646
|
+
cdp.click_visible_elements = CDPM.click_visible_elements
|
647
|
+
cdp.mouse_click = CDPM.mouse_click
|
648
|
+
cdp.remove_element = CDPM.remove_element
|
649
|
+
cdp.remove_from_dom = CDPM.remove_from_dom
|
650
|
+
cdp.remove_elements = CDPM.remove_elements
|
651
|
+
cdp.send_keys = CDPM.send_keys
|
652
|
+
cdp.press_keys = CDPM.press_keys
|
653
|
+
cdp.type = CDPM.type
|
654
|
+
cdp.set_value = CDPM.set_value
|
655
|
+
cdp.evaluate = CDPM.evaluate
|
656
|
+
cdp.js_dumps = CDPM.js_dumps
|
657
|
+
cdp.maximize = CDPM.maximize
|
658
|
+
cdp.minimize = CDPM.minimize
|
659
|
+
cdp.medimize = CDPM.medimize
|
660
|
+
cdp.set_window_rect = CDPM.set_window_rect
|
661
|
+
cdp.reset_window_size = CDPM.reset_window_size
|
662
|
+
cdp.set_locale = CDPM.set_locale
|
663
|
+
cdp.set_attributes = CDPM.set_attributes
|
664
|
+
cdp.gui_press_key = CDPM.gui_press_key
|
665
|
+
cdp.gui_press_keys = CDPM.gui_press_keys
|
666
|
+
cdp.gui_write = CDPM.gui_write
|
667
|
+
cdp.gui_click_x_y = CDPM.gui_click_x_y
|
668
|
+
cdp.gui_click_element = CDPM.gui_click_element
|
669
|
+
cdp.gui_drag_drop_points = CDPM.gui_drag_drop_points
|
670
|
+
cdp.gui_drag_and_drop = CDPM.gui_drag_and_drop
|
671
|
+
cdp.gui_hover_x_y = CDPM.gui_hover_x_y
|
672
|
+
cdp.gui_hover_element = CDPM.gui_hover_element
|
673
|
+
cdp.gui_hover_and_click = CDPM.gui_hover_and_click
|
674
|
+
cdp.internalize_links = CDPM.internalize_links
|
675
|
+
cdp.get_window = CDPM.get_window
|
676
|
+
cdp.get_element_attributes = CDPM.get_element_attributes
|
677
|
+
cdp.get_element_attribute = CDPM.get_element_attribute
|
678
|
+
cdp.get_attribute = CDPM.get_attribute
|
679
|
+
cdp.get_element_html = CDPM.get_element_html
|
680
|
+
cdp.get_element_rect = CDPM.get_element_rect
|
681
|
+
cdp.get_element_size = CDPM.get_element_size
|
682
|
+
cdp.get_element_position = CDPM.get_element_position
|
683
|
+
cdp.get_gui_element_rect = CDPM.get_gui_element_rect
|
684
|
+
cdp.get_gui_element_center = CDPM.get_gui_element_center
|
685
|
+
cdp.get_page_source = CDPM.get_page_source
|
686
|
+
cdp.get_user_agent = CDPM.get_user_agent
|
687
|
+
cdp.get_cookie_string = CDPM.get_cookie_string
|
688
|
+
cdp.get_locale_code = CDPM.get_locale_code
|
689
|
+
cdp.get_text = CDPM.get_text
|
690
|
+
cdp.get_title = CDPM.get_title
|
691
|
+
cdp.get_page_title = CDPM.get_title
|
692
|
+
cdp.get_current_url = CDPM.get_current_url
|
693
|
+
cdp.get_origin = CDPM.get_origin
|
694
|
+
cdp.get_nested_element = CDPM.get_nested_element
|
695
|
+
cdp.get_document = CDPM.get_document
|
696
|
+
cdp.get_flattened_document = CDPM.get_flattened_document
|
697
|
+
cdp.get_screen_rect = CDPM.get_screen_rect
|
698
|
+
cdp.get_window_rect = CDPM.get_window_rect
|
699
|
+
cdp.get_window_size = CDPM.get_window_size
|
700
|
+
cdp.nested_click = CDPM.nested_click
|
701
|
+
cdp.select_option_by_text = CDPM.select_option_by_text
|
702
|
+
cdp.flash = CDPM.flash
|
703
|
+
cdp.highlight = CDPM.highlight
|
704
|
+
cdp.focus = CDPM.focus
|
705
|
+
cdp.highlight_overlay = CDPM.highlight_overlay
|
706
|
+
cdp.get_window_position = CDPM.get_window_position
|
707
|
+
cdp.check_if_unchecked = CDPM.check_if_unchecked
|
708
|
+
cdp.uncheck_if_checked = CDPM.uncheck_if_checked
|
709
|
+
cdp.select_if_unselected = CDPM.select_if_unselected
|
710
|
+
cdp.unselect_if_selected = CDPM.unselect_if_selected
|
711
|
+
cdp.is_checked = CDPM.is_checked
|
712
|
+
cdp.is_selected = CDPM.is_selected
|
713
|
+
cdp.is_element_present = CDPM.is_element_present
|
714
|
+
cdp.is_element_visible = CDPM.is_element_visible
|
715
|
+
cdp.wait_for_element_visible = CDPM.wait_for_element_visible
|
716
|
+
cdp.assert_element = CDPM.assert_element
|
717
|
+
cdp.assert_element_visible = CDPM.assert_element_visible
|
718
|
+
cdp.assert_element_present = CDPM.assert_element_present
|
719
|
+
cdp.assert_element_absent = CDPM.assert_element_absent
|
720
|
+
cdp.assert_element_not_visible = CDPM.assert_element_not_visible
|
721
|
+
cdp.assert_element_attribute = CDPM.assert_element_attribute
|
722
|
+
cdp.assert_title = CDPM.assert_title
|
723
|
+
cdp.assert_title_contains = CDPM.assert_title_contains
|
724
|
+
cdp.assert_url = CDPM.assert_url
|
725
|
+
cdp.assert_url_contains = CDPM.assert_url_contains
|
726
|
+
cdp.assert_text = CDPM.assert_text
|
727
|
+
cdp.assert_exact_text = CDPM.assert_exact_text
|
728
|
+
cdp.assert_true = CDPM.assert_true
|
729
|
+
cdp.assert_false = CDPM.assert_false
|
730
|
+
cdp.assert_equal = CDPM.assert_equal
|
731
|
+
cdp.assert_not_equal = CDPM.assert_not_equal
|
732
|
+
cdp.assert_in = CDPM.assert_in
|
733
|
+
cdp.assert_not_in = CDPM.assert_not_in
|
734
|
+
cdp.scroll_into_view = CDPM.scroll_into_view
|
735
|
+
cdp.scroll_to_y = CDPM.scroll_to_y
|
736
|
+
cdp.scroll_to_top = CDPM.scroll_to_top
|
737
|
+
cdp.scroll_to_bottom = CDPM.scroll_to_bottom
|
738
|
+
cdp.scroll_up = CDPM.scroll_up
|
739
|
+
cdp.scroll_down = CDPM.scroll_down
|
740
|
+
cdp.save_screenshot = CDPM.save_screenshot
|
741
|
+
cdp.page = page # async world
|
742
|
+
cdp.driver = driver.cdp_base # async world
|
743
|
+
cdp.tab = cdp.page # shortcut (original)
|
744
|
+
cdp.browser = driver.cdp_base # shortcut (original)
|
745
|
+
cdp.util = cdp_util # shortcut (original)
|
746
|
+
core_items = types.SimpleNamespace()
|
747
|
+
core_items.browser = cdp.browser
|
748
|
+
core_items.tab = cdp.tab
|
749
|
+
core_items.util = cdp.util
|
750
|
+
cdp.core = core_items
|
751
|
+
cdp.loop = cdp.get_event_loop()
|
752
|
+
driver.cdp = cdp
|
753
|
+
driver._is_using_cdp = True
|
754
|
+
|
755
|
+
|
756
|
+
def uc_activate_cdp_mode(driver, url=None):
|
757
|
+
uc_open_with_cdp_mode(driver, url=url)
|
758
|
+
|
759
|
+
|
760
|
+
def uc_open_with_disconnect(driver, url, timeout=None):
|
761
|
+
"""Open a url and disconnect chromedriver.
|
762
|
+
Then waits for the duration of the timeout.
|
763
|
+
Note: You can't perform Selenium actions again
|
764
|
+
until after you've called driver.connect()."""
|
765
|
+
url = shared_utils.fix_url_as_needed(url)
|
766
|
+
if __is_cdp_swap_needed(driver):
|
767
|
+
driver.cdp.get(url)
|
768
|
+
time.sleep(0.3)
|
769
|
+
return
|
770
|
+
if not driver.is_connected():
|
771
|
+
driver.connect()
|
772
|
+
if (url.startswith("http:") or url.startswith("https:")):
|
773
|
+
script = 'window.open("%s","_blank");' % url
|
774
|
+
driver.execute_script(script)
|
775
|
+
time.sleep(0.05)
|
443
776
|
driver.close()
|
444
|
-
driver.
|
445
|
-
|
777
|
+
driver.disconnect()
|
778
|
+
min_timeout = 0.008
|
779
|
+
if timeout and not str(timeout).replace(".", "", 1).isdigit():
|
780
|
+
timeout = min_timeout
|
781
|
+
if not timeout or timeout < min_timeout:
|
782
|
+
timeout = min_timeout
|
783
|
+
time.sleep(timeout)
|
446
784
|
else:
|
447
785
|
driver.default_get(url) # The original one
|
448
786
|
return None
|
@@ -455,19 +793,25 @@ def uc_click(
|
|
455
793
|
timeout=settings.SMALL_TIMEOUT,
|
456
794
|
reconnect_time=None,
|
457
795
|
):
|
458
|
-
|
796
|
+
if __is_cdp_swap_needed(driver):
|
797
|
+
driver.cdp.click(selector)
|
798
|
+
return
|
799
|
+
with suppress(Exception):
|
459
800
|
rct = float(by) # Add shortcut: driver.uc_click(selector, RCT)
|
460
801
|
if not reconnect_time:
|
461
802
|
reconnect_time = rct
|
462
803
|
by = "css selector"
|
463
|
-
except Exception:
|
464
|
-
pass
|
465
804
|
element = driver.wait_for_selector(selector, by=by, timeout=timeout)
|
466
|
-
|
805
|
+
tag_name = element.tag_name
|
806
|
+
if not tag_name == "span" and not tag_name == "input": # Must be "visible"
|
467
807
|
element = driver.wait_for_element(selector, by=by, timeout=timeout)
|
468
808
|
try:
|
469
809
|
element.uc_click(
|
470
|
-
driver,
|
810
|
+
driver,
|
811
|
+
selector,
|
812
|
+
by=by,
|
813
|
+
reconnect_time=reconnect_time,
|
814
|
+
tag_name=tag_name,
|
471
815
|
)
|
472
816
|
except ElementClickInterceptedException:
|
473
817
|
time.sleep(0.16)
|
@@ -478,7 +822,801 @@ def uc_click(
|
|
478
822
|
driver.reconnect(reconnect_time)
|
479
823
|
|
480
824
|
|
481
|
-
def
|
825
|
+
def verify_pyautogui_has_a_headed_browser(driver):
|
826
|
+
"""PyAutoGUI requires a headed browser so that it can
|
827
|
+
focus on the correct element when performing actions."""
|
828
|
+
if hasattr(driver, "_is_hidden") and driver._is_hidden:
|
829
|
+
raise Exception(
|
830
|
+
"PyAutoGUI can't be used in headless mode!"
|
831
|
+
)
|
832
|
+
|
833
|
+
|
834
|
+
def __install_pyautogui_if_missing():
|
835
|
+
try:
|
836
|
+
import pyautogui
|
837
|
+
with suppress(Exception):
|
838
|
+
use_pyautogui_ver = constants.PyAutoGUI.VER
|
839
|
+
if pyautogui.__version__ != use_pyautogui_ver:
|
840
|
+
del pyautogui
|
841
|
+
shared_utils.pip_install(
|
842
|
+
"pyautogui", version=use_pyautogui_ver
|
843
|
+
)
|
844
|
+
import pyautogui
|
845
|
+
except Exception:
|
846
|
+
print("\nPyAutoGUI required! Installing now...")
|
847
|
+
shared_utils.pip_install(
|
848
|
+
"pyautogui", version=constants.PyAutoGUI.VER
|
849
|
+
)
|
850
|
+
try:
|
851
|
+
import pyautogui
|
852
|
+
except Exception:
|
853
|
+
if (
|
854
|
+
IS_LINUX
|
855
|
+
and hasattr(sb_config, "xvfb")
|
856
|
+
and hasattr(sb_config, "headed")
|
857
|
+
and hasattr(sb_config, "headless")
|
858
|
+
and hasattr(sb_config, "headless2")
|
859
|
+
and (not sb_config.headed or sb_config.xvfb)
|
860
|
+
and not (sb_config.headless or sb_config.headless2)
|
861
|
+
):
|
862
|
+
from sbvirtualdisplay import Display
|
863
|
+
xvfb_width = 1366
|
864
|
+
xvfb_height = 768
|
865
|
+
if (
|
866
|
+
hasattr(sb_config, "_xvfb_width")
|
867
|
+
and sb_config._xvfb_width
|
868
|
+
and isinstance(sb_config._xvfb_width, int)
|
869
|
+
and hasattr(sb_config, "_xvfb_height")
|
870
|
+
and sb_config._xvfb_height
|
871
|
+
and isinstance(sb_config._xvfb_height, int)
|
872
|
+
):
|
873
|
+
xvfb_width = sb_config._xvfb_width
|
874
|
+
xvfb_height = sb_config._xvfb_height
|
875
|
+
if xvfb_width < 1024:
|
876
|
+
xvfb_width = 1024
|
877
|
+
sb_config._xvfb_width = xvfb_width
|
878
|
+
if xvfb_height < 768:
|
879
|
+
xvfb_height = 768
|
880
|
+
sb_config._xvfb_height = xvfb_height
|
881
|
+
with suppress(Exception):
|
882
|
+
_xvfb_display = Display(
|
883
|
+
visible=True,
|
884
|
+
size=(xvfb_width, xvfb_height),
|
885
|
+
backend="xvfb",
|
886
|
+
use_xauth=True,
|
887
|
+
)
|
888
|
+
_xvfb_display.start()
|
889
|
+
sb_config._virtual_display = _xvfb_display
|
890
|
+
sb_config.headless_active = True
|
891
|
+
|
892
|
+
|
893
|
+
def install_pyautogui_if_missing(driver):
|
894
|
+
verify_pyautogui_has_a_headed_browser(driver)
|
895
|
+
pip_find_lock = fasteners.InterProcessLock(
|
896
|
+
constants.PipInstall.FINDLOCK
|
897
|
+
)
|
898
|
+
try:
|
899
|
+
with pip_find_lock:
|
900
|
+
pass
|
901
|
+
except Exception:
|
902
|
+
# Since missing permissions, skip the locks
|
903
|
+
__install_pyautogui_if_missing()
|
904
|
+
return
|
905
|
+
with pip_find_lock: # Prevent issues with multiple processes
|
906
|
+
with suppress(Exception):
|
907
|
+
shared_utils.make_writable(constants.PipInstall.FINDLOCK)
|
908
|
+
__install_pyautogui_if_missing()
|
909
|
+
|
910
|
+
|
911
|
+
def get_configured_pyautogui(pyautogui_copy):
|
912
|
+
if (
|
913
|
+
IS_LINUX
|
914
|
+
and hasattr(pyautogui_copy, "_pyautogui_x11")
|
915
|
+
and "DISPLAY" in os.environ.keys()
|
916
|
+
):
|
917
|
+
if (
|
918
|
+
hasattr(sb_config, "_pyautogui_x11_display")
|
919
|
+
and sb_config._pyautogui_x11_display
|
920
|
+
and hasattr(pyautogui_copy._pyautogui_x11, "_display")
|
921
|
+
and (
|
922
|
+
sb_config._pyautogui_x11_display
|
923
|
+
== pyautogui_copy._pyautogui_x11._display
|
924
|
+
)
|
925
|
+
):
|
926
|
+
pass
|
927
|
+
else:
|
928
|
+
import Xlib.display
|
929
|
+
pyautogui_copy._pyautogui_x11._display = (
|
930
|
+
Xlib.display.Display(os.environ['DISPLAY'])
|
931
|
+
)
|
932
|
+
sb_config._pyautogui_x11_display = (
|
933
|
+
pyautogui_copy._pyautogui_x11._display
|
934
|
+
)
|
935
|
+
return pyautogui_copy
|
936
|
+
|
937
|
+
|
938
|
+
def uc_gui_press_key(driver, key):
|
939
|
+
install_pyautogui_if_missing(driver)
|
940
|
+
import pyautogui
|
941
|
+
pyautogui = get_configured_pyautogui(pyautogui)
|
942
|
+
gui_lock = fasteners.InterProcessLock(
|
943
|
+
constants.MultiBrowser.PYAUTOGUILOCK
|
944
|
+
)
|
945
|
+
with gui_lock:
|
946
|
+
pyautogui.press(key)
|
947
|
+
|
948
|
+
|
949
|
+
def uc_gui_press_keys(driver, keys):
|
950
|
+
install_pyautogui_if_missing(driver)
|
951
|
+
import pyautogui
|
952
|
+
pyautogui = get_configured_pyautogui(pyautogui)
|
953
|
+
gui_lock = fasteners.InterProcessLock(
|
954
|
+
constants.MultiBrowser.PYAUTOGUILOCK
|
955
|
+
)
|
956
|
+
with gui_lock:
|
957
|
+
for key in keys:
|
958
|
+
pyautogui.press(key)
|
959
|
+
|
960
|
+
|
961
|
+
def uc_gui_write(driver, text):
|
962
|
+
install_pyautogui_if_missing(driver)
|
963
|
+
import pyautogui
|
964
|
+
pyautogui = get_configured_pyautogui(pyautogui)
|
965
|
+
gui_lock = fasteners.InterProcessLock(
|
966
|
+
constants.MultiBrowser.PYAUTOGUILOCK
|
967
|
+
)
|
968
|
+
with gui_lock:
|
969
|
+
pyautogui.write(text)
|
970
|
+
|
971
|
+
|
972
|
+
def get_gui_element_position(driver, selector):
|
973
|
+
if __is_cdp_swap_needed(driver):
|
974
|
+
element_rect = driver.cdp.get_gui_element_rect(selector)
|
975
|
+
return (element_rect["x"], element_rect["y"])
|
976
|
+
element = driver.wait_for_element_present(selector, timeout=3)
|
977
|
+
element_rect = element.rect
|
978
|
+
window_rect = driver.get_window_rect()
|
979
|
+
window_bottom_y = window_rect["y"] + window_rect["height"]
|
980
|
+
viewport_height = driver.execute_script("return window.innerHeight;")
|
981
|
+
viewport_x = window_rect["x"] + element_rect["x"]
|
982
|
+
viewport_y = window_bottom_y - viewport_height + element_rect["y"]
|
983
|
+
y_scroll_offset = driver.execute_script("return window.pageYOffset;")
|
984
|
+
viewport_y = viewport_y - y_scroll_offset
|
985
|
+
return (viewport_x, viewport_y)
|
986
|
+
|
987
|
+
|
988
|
+
def _uc_gui_click_x_y(driver, x, y, timeframe=0.25, uc_lock=False):
|
989
|
+
install_pyautogui_if_missing(driver)
|
990
|
+
import pyautogui
|
991
|
+
pyautogui = get_configured_pyautogui(pyautogui)
|
992
|
+
screen_width, screen_height = pyautogui.size()
|
993
|
+
if x < 0 or y < 0 or x > screen_width or y > screen_height:
|
994
|
+
raise Exception(
|
995
|
+
"PyAutoGUI cannot click on point (%s, %s)"
|
996
|
+
" outside screen. (Width: %s, Height: %s)"
|
997
|
+
% (x, y, screen_width, screen_height)
|
998
|
+
)
|
999
|
+
if uc_lock:
|
1000
|
+
gui_lock = fasteners.InterProcessLock(
|
1001
|
+
constants.MultiBrowser.PYAUTOGUILOCK
|
1002
|
+
)
|
1003
|
+
with gui_lock: # Prevent issues with multiple processes
|
1004
|
+
pyautogui.moveTo(x, y, timeframe, pyautogui.easeOutQuad)
|
1005
|
+
if timeframe >= 0.25:
|
1006
|
+
time.sleep(0.056) # Wait if moving at human-speed
|
1007
|
+
if "--debug" in sys.argv:
|
1008
|
+
print(" <DEBUG> pyautogui.click(%s, %s)" % (x, y))
|
1009
|
+
pyautogui.click(x=x, y=y)
|
1010
|
+
else:
|
1011
|
+
# Called from a method where the gui_lock is already active
|
1012
|
+
pyautogui.moveTo(x, y, timeframe, pyautogui.easeOutQuad)
|
1013
|
+
if timeframe >= 0.25:
|
1014
|
+
time.sleep(0.056) # Wait if moving at human-speed
|
1015
|
+
if "--debug" in sys.argv:
|
1016
|
+
print(" <DEBUG> pyautogui.click(%s, %s)" % (x, y))
|
1017
|
+
pyautogui.click(x=x, y=y)
|
1018
|
+
|
1019
|
+
|
1020
|
+
def uc_gui_click_x_y(driver, x, y, timeframe=0.25):
|
1021
|
+
gui_lock = fasteners.InterProcessLock(
|
1022
|
+
constants.MultiBrowser.PYAUTOGUILOCK
|
1023
|
+
)
|
1024
|
+
with gui_lock: # Prevent issues with multiple processes
|
1025
|
+
install_pyautogui_if_missing(driver)
|
1026
|
+
import pyautogui
|
1027
|
+
pyautogui = get_configured_pyautogui(pyautogui)
|
1028
|
+
connected = True
|
1029
|
+
width_ratio = 1.0
|
1030
|
+
if IS_WINDOWS:
|
1031
|
+
connected = driver.is_connected()
|
1032
|
+
if (
|
1033
|
+
not connected
|
1034
|
+
and (
|
1035
|
+
not hasattr(sb_config, "_saved_width_ratio")
|
1036
|
+
or not sb_config._saved_width_ratio
|
1037
|
+
)
|
1038
|
+
and not __is_cdp_swap_needed(driver)
|
1039
|
+
):
|
1040
|
+
driver.reconnect(0.1)
|
1041
|
+
if IS_WINDOWS and not __is_cdp_swap_needed(driver):
|
1042
|
+
window_rect = driver.get_window_rect()
|
1043
|
+
width = window_rect["width"]
|
1044
|
+
height = window_rect["height"]
|
1045
|
+
win_x = window_rect["x"]
|
1046
|
+
win_y = window_rect["y"]
|
1047
|
+
scr_width = pyautogui.size().width
|
1048
|
+
driver.maximize_window()
|
1049
|
+
win_width = driver.get_window_size()["width"]
|
1050
|
+
width_ratio = round(float(scr_width) / float(win_width), 2) + 0.01
|
1051
|
+
if width_ratio < 0.45 or width_ratio > 2.55:
|
1052
|
+
width_ratio = 1.01
|
1053
|
+
sb_config._saved_width_ratio = width_ratio
|
1054
|
+
driver.minimize_window()
|
1055
|
+
driver.set_window_rect(win_x, win_y, width, height)
|
1056
|
+
elif IS_WINDOWS and __is_cdp_swap_needed(driver):
|
1057
|
+
window_rect = driver.cdp.get_window_rect()
|
1058
|
+
width = window_rect["width"]
|
1059
|
+
height = window_rect["height"]
|
1060
|
+
win_x = window_rect["x"]
|
1061
|
+
win_y = window_rect["y"]
|
1062
|
+
scr_width = pyautogui.size().width
|
1063
|
+
driver.cdp.maximize()
|
1064
|
+
win_width = driver.cdp.get_window_size()["width"]
|
1065
|
+
width_ratio = round(float(scr_width) / float(win_width), 2) + 0.01
|
1066
|
+
if width_ratio < 0.45 or width_ratio > 2.55:
|
1067
|
+
width_ratio = 1.01
|
1068
|
+
sb_config._saved_width_ratio = width_ratio
|
1069
|
+
driver.cdp.minimize()
|
1070
|
+
driver.cdp.set_window_rect(win_x, win_y, width, height)
|
1071
|
+
if IS_WINDOWS:
|
1072
|
+
x = x * width_ratio
|
1073
|
+
y = y * width_ratio
|
1074
|
+
_uc_gui_click_x_y(driver, x, y, timeframe=timeframe, uc_lock=False)
|
1075
|
+
return
|
1076
|
+
with suppress(Exception):
|
1077
|
+
page_actions.switch_to_window(
|
1078
|
+
driver, driver.current_window_handle, 2, uc_lock=False
|
1079
|
+
)
|
1080
|
+
_uc_gui_click_x_y(driver, x, y, timeframe=timeframe, uc_lock=False)
|
1081
|
+
|
1082
|
+
|
1083
|
+
def _on_a_cf_turnstile_page(driver):
|
1084
|
+
source = driver.get_page_source()
|
1085
|
+
if (
|
1086
|
+
'data-callback="onCaptchaSuccess"' in source
|
1087
|
+
or "/challenge-platform/scripts/" in source
|
1088
|
+
or 'id="challenge-widget-' in source
|
1089
|
+
or "cf-turnstile-" in source
|
1090
|
+
):
|
1091
|
+
return True
|
1092
|
+
return False
|
1093
|
+
|
1094
|
+
|
1095
|
+
def _on_a_g_recaptcha_page(driver):
|
1096
|
+
source = driver.get_page_source()
|
1097
|
+
if (
|
1098
|
+
'id="recaptcha-token"' in source
|
1099
|
+
or 'title="reCAPTCHA"' in source
|
1100
|
+
):
|
1101
|
+
return True
|
1102
|
+
return False
|
1103
|
+
|
1104
|
+
|
1105
|
+
def _uc_gui_click_captcha(
|
1106
|
+
driver,
|
1107
|
+
frame="iframe",
|
1108
|
+
retry=False,
|
1109
|
+
blind=False,
|
1110
|
+
ctype=None,
|
1111
|
+
):
|
1112
|
+
cdp_mode_on_at_start = __is_cdp_swap_needed(driver)
|
1113
|
+
_on_a_captcha_page = None
|
1114
|
+
if ctype == "cf_t":
|
1115
|
+
if not _on_a_cf_turnstile_page(driver):
|
1116
|
+
return
|
1117
|
+
else:
|
1118
|
+
_on_a_captcha_page = _on_a_cf_turnstile_page
|
1119
|
+
elif ctype == "g_rc":
|
1120
|
+
if not _on_a_g_recaptcha_page(driver):
|
1121
|
+
return
|
1122
|
+
else:
|
1123
|
+
_on_a_captcha_page = _on_a_g_recaptcha_page
|
1124
|
+
else:
|
1125
|
+
if _on_a_g_recaptcha_page(driver):
|
1126
|
+
ctype = "g_rc"
|
1127
|
+
_on_a_captcha_page = _on_a_g_recaptcha_page
|
1128
|
+
elif _on_a_cf_turnstile_page(driver):
|
1129
|
+
ctype = "cf_t"
|
1130
|
+
_on_a_captcha_page = _on_a_cf_turnstile_page
|
1131
|
+
else:
|
1132
|
+
return
|
1133
|
+
install_pyautogui_if_missing(driver)
|
1134
|
+
import pyautogui
|
1135
|
+
pyautogui = get_configured_pyautogui(pyautogui)
|
1136
|
+
i_x = None
|
1137
|
+
i_y = None
|
1138
|
+
x = None
|
1139
|
+
y = None
|
1140
|
+
visible_iframe = True
|
1141
|
+
gui_lock = fasteners.InterProcessLock(
|
1142
|
+
constants.MultiBrowser.PYAUTOGUILOCK
|
1143
|
+
)
|
1144
|
+
with gui_lock: # Prevent issues with multiple processes
|
1145
|
+
needs_switch = False
|
1146
|
+
width_ratio = 1.0
|
1147
|
+
is_in_frame = js_utils.is_in_frame(driver)
|
1148
|
+
if is_in_frame and driver.is_element_present("#challenge-stage"):
|
1149
|
+
driver.switch_to.parent_frame()
|
1150
|
+
needs_switch = True
|
1151
|
+
is_in_frame = js_utils.is_in_frame(driver)
|
1152
|
+
if not is_in_frame:
|
1153
|
+
# Make sure the window is on top
|
1154
|
+
if __is_cdp_swap_needed(driver):
|
1155
|
+
driver.cdp.bring_active_window_to_front()
|
1156
|
+
else:
|
1157
|
+
page_actions.switch_to_window(
|
1158
|
+
driver, driver.current_window_handle, 2, uc_lock=False
|
1159
|
+
)
|
1160
|
+
if IS_WINDOWS and not __is_cdp_swap_needed(driver):
|
1161
|
+
window_rect = driver.get_window_rect()
|
1162
|
+
width = window_rect["width"]
|
1163
|
+
height = window_rect["height"]
|
1164
|
+
win_x = window_rect["x"]
|
1165
|
+
win_y = window_rect["y"]
|
1166
|
+
scr_width = pyautogui.size().width
|
1167
|
+
driver.maximize_window()
|
1168
|
+
win_width = driver.get_window_size()["width"]
|
1169
|
+
width_ratio = round(float(scr_width) / float(win_width), 2) + 0.01
|
1170
|
+
if width_ratio < 0.45 or width_ratio > 2.55:
|
1171
|
+
width_ratio = 1.01
|
1172
|
+
sb_config._saved_width_ratio = width_ratio
|
1173
|
+
driver.minimize_window()
|
1174
|
+
driver.set_window_rect(win_x, win_y, width, height)
|
1175
|
+
elif IS_WINDOWS and __is_cdp_swap_needed(driver):
|
1176
|
+
window_rect = driver.cdp.get_window_rect()
|
1177
|
+
width = window_rect["width"]
|
1178
|
+
height = window_rect["height"]
|
1179
|
+
win_x = window_rect["x"]
|
1180
|
+
win_y = window_rect["y"]
|
1181
|
+
scr_width = pyautogui.size().width
|
1182
|
+
driver.cdp.maximize()
|
1183
|
+
win_width = driver.cdp.get_window_size()["width"]
|
1184
|
+
width_ratio = round(float(scr_width) / float(win_width), 2) + 0.01
|
1185
|
+
if width_ratio < 0.45 or width_ratio > 2.55:
|
1186
|
+
width_ratio = 1.01
|
1187
|
+
sb_config._saved_width_ratio = width_ratio
|
1188
|
+
driver.cdp.minimize()
|
1189
|
+
driver.cdp.set_window_rect(win_x, win_y, width, height)
|
1190
|
+
if ctype == "cf_t":
|
1191
|
+
if (
|
1192
|
+
driver.is_element_present(".cf-turnstile-wrapper iframe")
|
1193
|
+
or driver.is_element_present(
|
1194
|
+
'[data-callback="onCaptchaSuccess"] iframe'
|
1195
|
+
)
|
1196
|
+
):
|
1197
|
+
pass
|
1198
|
+
else:
|
1199
|
+
visible_iframe = False
|
1200
|
+
if (
|
1201
|
+
frame != "iframe"
|
1202
|
+
and driver.is_element_present(
|
1203
|
+
"%s .cf-turnstile-wrapper" % frame
|
1204
|
+
)
|
1205
|
+
):
|
1206
|
+
frame = "%s .cf-turnstile-wrapper" % frame
|
1207
|
+
elif (
|
1208
|
+
frame != "iframe"
|
1209
|
+
and driver.is_element_present(
|
1210
|
+
'%s [name*="cf-turnstile"]' % frame
|
1211
|
+
)
|
1212
|
+
and driver.is_element_present("%s div" % frame)
|
1213
|
+
):
|
1214
|
+
frame = "%s div" % frame
|
1215
|
+
elif (
|
1216
|
+
driver.is_element_present('[name*="cf-turnstile-"]')
|
1217
|
+
and driver.is_element_present("#challenge-form div > div")
|
1218
|
+
):
|
1219
|
+
frame = "#challenge-form div > div"
|
1220
|
+
elif (
|
1221
|
+
driver.is_element_present('[name*="cf-turnstile-"]')
|
1222
|
+
and driver.is_element_present("[class*=spacer] + div div")
|
1223
|
+
):
|
1224
|
+
frame = '[class*=spacer] + div div'
|
1225
|
+
elif (
|
1226
|
+
driver.is_element_present('[name*="cf-turnstile-"]')
|
1227
|
+
and driver.is_element_present("div.spacer div")
|
1228
|
+
):
|
1229
|
+
frame = "div.spacer div"
|
1230
|
+
elif (
|
1231
|
+
driver.is_element_present('script[src*="challenges.c"]')
|
1232
|
+
and driver.is_element_present(
|
1233
|
+
'[data-testid*="challenge-"] div'
|
1234
|
+
)
|
1235
|
+
):
|
1236
|
+
frame = '[data-testid*="challenge-"] div'
|
1237
|
+
elif driver.is_element_present(
|
1238
|
+
'form div:not([class]):has(input[name*="cf-turn"])'
|
1239
|
+
):
|
1240
|
+
frame = 'form div:not([class]):has(input[name*="cf-turn"])'
|
1241
|
+
elif (
|
1242
|
+
driver.is_element_present('[src*="/turnstile/"]')
|
1243
|
+
and driver.is_element_present("form div:not(:has(*))")
|
1244
|
+
):
|
1245
|
+
frame = "form div:not(:has(*))"
|
1246
|
+
elif driver.is_element_present(".cf-turnstile-wrapper"):
|
1247
|
+
frame = ".cf-turnstile-wrapper"
|
1248
|
+
elif driver.is_element_present(
|
1249
|
+
'[data-callback="onCaptchaSuccess"]'
|
1250
|
+
):
|
1251
|
+
frame = '[data-callback="onCaptchaSuccess"]'
|
1252
|
+
else:
|
1253
|
+
return
|
1254
|
+
if (
|
1255
|
+
driver.is_element_present("form")
|
1256
|
+
and (
|
1257
|
+
driver.is_element_present('form[class*="center"]')
|
1258
|
+
or driver.is_element_present('form[class*="right"]')
|
1259
|
+
or driver.is_element_present('form div[class*="center"]')
|
1260
|
+
or driver.is_element_present('form div[class*="right"]')
|
1261
|
+
)
|
1262
|
+
):
|
1263
|
+
script = (
|
1264
|
+
"""var $elements = document.querySelectorAll(
|
1265
|
+
'form[class], form div[class]');
|
1266
|
+
var index = 0, length = $elements.length;
|
1267
|
+
for(; index < length; index++){
|
1268
|
+
the_class = $elements[index].getAttribute('class');
|
1269
|
+
new_class = the_class.replaceAll('center', 'left');
|
1270
|
+
new_class = new_class.replaceAll('right', 'left');
|
1271
|
+
$elements[index].setAttribute('class', new_class);}"""
|
1272
|
+
)
|
1273
|
+
if __is_cdp_swap_needed(driver):
|
1274
|
+
driver.cdp.evaluate(script)
|
1275
|
+
else:
|
1276
|
+
driver.execute_script(script)
|
1277
|
+
if not is_in_frame or needs_switch:
|
1278
|
+
# Currently not in frame (or nested frame outside CF one)
|
1279
|
+
try:
|
1280
|
+
i_x, i_y = get_gui_element_position(driver, frame)
|
1281
|
+
if visible_iframe:
|
1282
|
+
driver.switch_to_frame(frame)
|
1283
|
+
except Exception:
|
1284
|
+
if visible_iframe:
|
1285
|
+
if driver.is_element_present("iframe"):
|
1286
|
+
i_x, i_y = get_gui_element_position(driver, "iframe")
|
1287
|
+
if driver.is_connected():
|
1288
|
+
driver.switch_to_frame("iframe")
|
1289
|
+
else:
|
1290
|
+
return
|
1291
|
+
if not i_x or not i_y:
|
1292
|
+
return
|
1293
|
+
try:
|
1294
|
+
if ctype == "g_rc" and not driver.is_connected():
|
1295
|
+
x = (i_x + 29) * width_ratio
|
1296
|
+
y = (i_y + 35) * width_ratio
|
1297
|
+
elif visible_iframe:
|
1298
|
+
selector = "span"
|
1299
|
+
if ctype == "g_rc":
|
1300
|
+
selector = "span.recaptcha-checkbox"
|
1301
|
+
if not driver.is_connected():
|
1302
|
+
selector = "iframe"
|
1303
|
+
element = driver.wait_for_element_present(
|
1304
|
+
selector, timeout=2.5
|
1305
|
+
)
|
1306
|
+
x = i_x + element.rect["x"] + (element.rect["width"] / 2.0)
|
1307
|
+
x += 0.5
|
1308
|
+
y = i_y + element.rect["y"] + (element.rect["height"] / 2.0)
|
1309
|
+
y += 0.5
|
1310
|
+
else:
|
1311
|
+
x = (i_x + 32) * width_ratio
|
1312
|
+
y = (i_y + 32) * width_ratio
|
1313
|
+
if driver.is_connected():
|
1314
|
+
driver.switch_to.default_content()
|
1315
|
+
except Exception:
|
1316
|
+
if driver.is_connected():
|
1317
|
+
try:
|
1318
|
+
driver.switch_to.default_content()
|
1319
|
+
except Exception:
|
1320
|
+
return
|
1321
|
+
if x and y:
|
1322
|
+
sb_config._saved_cf_x_y = (x, y)
|
1323
|
+
if not __is_cdp_swap_needed(driver):
|
1324
|
+
if driver.is_element_present(".footer .clearfix .ray-id"):
|
1325
|
+
driver.uc_open_with_disconnect(
|
1326
|
+
driver.get_current_url(), 3.8
|
1327
|
+
)
|
1328
|
+
else:
|
1329
|
+
driver.disconnect()
|
1330
|
+
with suppress(Exception):
|
1331
|
+
_uc_gui_click_x_y(driver, x, y, timeframe=0.32)
|
1332
|
+
if __is_cdp_swap_needed(driver):
|
1333
|
+
time.sleep(float(constants.UC.RECONNECT_TIME) / 2.0)
|
1334
|
+
return
|
1335
|
+
reconnect_time = (float(constants.UC.RECONNECT_TIME) / 2.0) + 0.6
|
1336
|
+
if IS_LINUX:
|
1337
|
+
reconnect_time = constants.UC.RECONNECT_TIME + 0.2
|
1338
|
+
if not x or not y:
|
1339
|
+
reconnect_time = 1 # Make it quick (it already failed)
|
1340
|
+
driver.reconnect(reconnect_time)
|
1341
|
+
caught = False
|
1342
|
+
if (
|
1343
|
+
driver.is_element_present(".footer .clearfix .ray-id")
|
1344
|
+
and not driver.is_element_visible("#challenge-success-text")
|
1345
|
+
):
|
1346
|
+
blind = True
|
1347
|
+
caught = True
|
1348
|
+
if blind:
|
1349
|
+
retry = True
|
1350
|
+
if retry and x and y and (caught or _on_a_captcha_page(driver)):
|
1351
|
+
with gui_lock: # Prevent issues with multiple processes
|
1352
|
+
# Make sure the window is on top
|
1353
|
+
if __is_cdp_swap_needed(driver):
|
1354
|
+
driver.cdp.bring_active_window_to_front()
|
1355
|
+
else:
|
1356
|
+
page_actions.switch_to_window(
|
1357
|
+
driver, driver.current_window_handle, 2, uc_lock=False
|
1358
|
+
)
|
1359
|
+
if driver.is_element_present("iframe"):
|
1360
|
+
try:
|
1361
|
+
driver.switch_to_frame(frame)
|
1362
|
+
except Exception:
|
1363
|
+
try:
|
1364
|
+
driver.switch_to_frame("iframe")
|
1365
|
+
except Exception:
|
1366
|
+
return
|
1367
|
+
checkbox_success = None
|
1368
|
+
if ctype == "cf_t":
|
1369
|
+
checkbox_success = "#success-icon"
|
1370
|
+
elif ctype == "g_rc":
|
1371
|
+
checkbox_success = "span.recaptcha-checkbox-checked"
|
1372
|
+
else:
|
1373
|
+
return # If this line is reached, ctype wasn't set
|
1374
|
+
if driver.is_element_visible("#success-icon"):
|
1375
|
+
driver.switch_to.parent_frame(checkbox_success)
|
1376
|
+
return
|
1377
|
+
if blind:
|
1378
|
+
driver.uc_open_with_disconnect(driver.get_current_url(), 3.8)
|
1379
|
+
if __is_cdp_swap_needed(driver) and _on_a_captcha_page(driver):
|
1380
|
+
_uc_gui_click_x_y(driver, x, y, timeframe=0.32)
|
1381
|
+
else:
|
1382
|
+
time.sleep(0.1)
|
1383
|
+
else:
|
1384
|
+
driver.uc_open_with_reconnect(driver.get_current_url(), 3.8)
|
1385
|
+
if _on_a_captcha_page(driver):
|
1386
|
+
driver.disconnect()
|
1387
|
+
_uc_gui_click_x_y(driver, x, y, timeframe=0.32)
|
1388
|
+
if not cdp_mode_on_at_start:
|
1389
|
+
driver.reconnect(reconnect_time)
|
1390
|
+
|
1391
|
+
|
1392
|
+
def uc_gui_click_captcha(driver, frame="iframe", retry=False, blind=False):
|
1393
|
+
_uc_gui_click_captcha(
|
1394
|
+
driver,
|
1395
|
+
frame=frame,
|
1396
|
+
retry=retry,
|
1397
|
+
blind=blind,
|
1398
|
+
ctype=None,
|
1399
|
+
)
|
1400
|
+
|
1401
|
+
|
1402
|
+
def uc_gui_click_rc(driver, frame="iframe", retry=False, blind=False):
|
1403
|
+
_uc_gui_click_captcha(
|
1404
|
+
driver,
|
1405
|
+
frame=frame,
|
1406
|
+
retry=retry,
|
1407
|
+
blind=blind,
|
1408
|
+
ctype="g_rc",
|
1409
|
+
)
|
1410
|
+
|
1411
|
+
|
1412
|
+
def uc_gui_click_cf(driver, frame="iframe", retry=False, blind=False):
|
1413
|
+
_uc_gui_click_captcha(
|
1414
|
+
driver,
|
1415
|
+
frame=frame,
|
1416
|
+
retry=retry,
|
1417
|
+
blind=blind,
|
1418
|
+
ctype="cf_t",
|
1419
|
+
)
|
1420
|
+
|
1421
|
+
|
1422
|
+
def _uc_gui_handle_captcha_(driver, frame="iframe", ctype=None):
|
1423
|
+
if ctype == "cf_t":
|
1424
|
+
if not _on_a_cf_turnstile_page(driver):
|
1425
|
+
return
|
1426
|
+
elif ctype == "g_rc":
|
1427
|
+
if not _on_a_g_recaptcha_page(driver):
|
1428
|
+
return
|
1429
|
+
else:
|
1430
|
+
if _on_a_g_recaptcha_page(driver):
|
1431
|
+
ctype = "g_rc"
|
1432
|
+
elif _on_a_cf_turnstile_page(driver):
|
1433
|
+
ctype = "cf_t"
|
1434
|
+
else:
|
1435
|
+
return
|
1436
|
+
if not driver.is_connected() and not __is_cdp_swap_needed(driver):
|
1437
|
+
driver.connect()
|
1438
|
+
time.sleep(2)
|
1439
|
+
install_pyautogui_if_missing(driver)
|
1440
|
+
import pyautogui
|
1441
|
+
pyautogui = get_configured_pyautogui(pyautogui)
|
1442
|
+
visible_iframe = True
|
1443
|
+
gui_lock = fasteners.InterProcessLock(
|
1444
|
+
constants.MultiBrowser.PYAUTOGUILOCK
|
1445
|
+
)
|
1446
|
+
with gui_lock: # Prevent issues with multiple processes
|
1447
|
+
needs_switch = False
|
1448
|
+
if not __is_cdp_swap_needed(driver):
|
1449
|
+
is_in_frame = js_utils.is_in_frame(driver)
|
1450
|
+
else:
|
1451
|
+
is_in_frame = False
|
1452
|
+
selector = "#challenge-stage"
|
1453
|
+
if ctype == "g_rc":
|
1454
|
+
selector = "#recaptcha-token"
|
1455
|
+
if is_in_frame and driver.is_element_present(selector):
|
1456
|
+
driver.switch_to.parent_frame()
|
1457
|
+
needs_switch = True
|
1458
|
+
is_in_frame = js_utils.is_in_frame(driver)
|
1459
|
+
if not is_in_frame and not __is_cdp_swap_needed(driver):
|
1460
|
+
# Make sure the window is on top
|
1461
|
+
page_actions.switch_to_window(
|
1462
|
+
driver, driver.current_window_handle, 2, uc_lock=False
|
1463
|
+
)
|
1464
|
+
if IS_WINDOWS and hasattr(pyautogui, "getActiveWindowTitle"):
|
1465
|
+
py_a_g_title = pyautogui.getActiveWindowTitle() or ""
|
1466
|
+
window_title = driver.get_title()
|
1467
|
+
if not py_a_g_title.startswith(window_title):
|
1468
|
+
window_rect = driver.get_window_rect()
|
1469
|
+
width = window_rect["width"]
|
1470
|
+
height = window_rect["height"]
|
1471
|
+
win_x = window_rect["x"]
|
1472
|
+
win_y = window_rect["y"]
|
1473
|
+
driver.minimize_window()
|
1474
|
+
driver.set_window_rect(win_x, win_y, width, height)
|
1475
|
+
time.sleep(0.33)
|
1476
|
+
tab_up_first = False
|
1477
|
+
special_form = False
|
1478
|
+
if ctype == "cf_t":
|
1479
|
+
if (
|
1480
|
+
driver.is_element_present(".cf-turnstile-wrapper iframe")
|
1481
|
+
or driver.is_element_present(
|
1482
|
+
'[data-callback="onCaptchaSuccess"] iframe'
|
1483
|
+
)
|
1484
|
+
):
|
1485
|
+
pass
|
1486
|
+
else:
|
1487
|
+
visible_iframe = False
|
1488
|
+
if driver.is_element_present(".cf-turnstile-wrapper"):
|
1489
|
+
frame = ".cf-turnstile-wrapper"
|
1490
|
+
elif driver.is_element_present(
|
1491
|
+
'[data-callback="onCaptchaSuccess"]'
|
1492
|
+
):
|
1493
|
+
frame = '[data-callback="onCaptchaSuccess"]'
|
1494
|
+
elif (
|
1495
|
+
driver.is_element_present('[name*="cf-turnstile-"]')
|
1496
|
+
and driver.is_element_present("div.spacer div")
|
1497
|
+
):
|
1498
|
+
frame = "div.spacer div"
|
1499
|
+
elif (
|
1500
|
+
driver.is_element_present('script[src*="challenges.c"]')
|
1501
|
+
and driver.is_element_present(
|
1502
|
+
'[data-testid*="challenge-"] div'
|
1503
|
+
)
|
1504
|
+
):
|
1505
|
+
frame = '[data-testid*="challenge-"] div'
|
1506
|
+
elif driver.is_element_present(
|
1507
|
+
'form div:not([class]):has(input[name*="cf-turn"])'
|
1508
|
+
):
|
1509
|
+
frame = 'form div:not([class]):has(input[name*="cf-turn"])'
|
1510
|
+
tab_up_first = True
|
1511
|
+
special_form = True
|
1512
|
+
elif (
|
1513
|
+
driver.is_element_present('[src*="/turnstile/"]')
|
1514
|
+
and driver.is_element_present("form div:not(:has(*))")
|
1515
|
+
):
|
1516
|
+
frame = "form div:not(:has(*))"
|
1517
|
+
tab_up_first = True
|
1518
|
+
else:
|
1519
|
+
return
|
1520
|
+
else:
|
1521
|
+
if (
|
1522
|
+
driver.is_element_present('iframe[title="reCAPTCHA"]')
|
1523
|
+
and frame == "iframe"
|
1524
|
+
):
|
1525
|
+
frame = 'iframe[title="reCAPTCHA"]'
|
1526
|
+
if not __is_cdp_swap_needed(driver):
|
1527
|
+
if not is_in_frame or needs_switch:
|
1528
|
+
# Currently not in frame (or nested frame outside CF one)
|
1529
|
+
try:
|
1530
|
+
if visible_iframe or ctype == "g_rc":
|
1531
|
+
driver.switch_to_frame(frame)
|
1532
|
+
except Exception:
|
1533
|
+
if visible_iframe or ctype == "g_rc":
|
1534
|
+
if driver.is_element_present("iframe"):
|
1535
|
+
driver.switch_to_frame("iframe")
|
1536
|
+
else:
|
1537
|
+
return
|
1538
|
+
try:
|
1539
|
+
selector = "div.cf-turnstile"
|
1540
|
+
if ctype == "g_rc":
|
1541
|
+
selector = "span#recaptcha-anchor"
|
1542
|
+
found_checkbox = False
|
1543
|
+
if tab_up_first:
|
1544
|
+
for i in range(10):
|
1545
|
+
pyautogui.hotkey("shift", "tab")
|
1546
|
+
time.sleep(0.027)
|
1547
|
+
if ctype == "g_rc":
|
1548
|
+
if js_utils.get_active_element_css(driver) == "body":
|
1549
|
+
break
|
1550
|
+
tab_count = 0
|
1551
|
+
for i in range(34):
|
1552
|
+
pyautogui.press("\t")
|
1553
|
+
tab_count += 1
|
1554
|
+
time.sleep(0.027)
|
1555
|
+
active_element_css = js_utils.get_active_element_css(driver)
|
1556
|
+
if (
|
1557
|
+
active_element_css.startswith(selector)
|
1558
|
+
or active_element_css.endswith(" > div" * 2)
|
1559
|
+
or (special_form and active_element_css.endswith(" div"))
|
1560
|
+
or (ctype == "g_rc" and "frame[name" in active_element_css)
|
1561
|
+
):
|
1562
|
+
found_checkbox = True
|
1563
|
+
sb_config._saved_cf_tab_count = tab_count
|
1564
|
+
break
|
1565
|
+
time.sleep(0.02)
|
1566
|
+
if not found_checkbox:
|
1567
|
+
return
|
1568
|
+
except Exception:
|
1569
|
+
try:
|
1570
|
+
driver.switch_to.default_content()
|
1571
|
+
except Exception:
|
1572
|
+
return
|
1573
|
+
if (
|
1574
|
+
(
|
1575
|
+
driver.is_element_present(".footer .clearfix .ray-id")
|
1576
|
+
or driver.is_element_present("script[data-cf-beacon]")
|
1577
|
+
)
|
1578
|
+
and hasattr(sb_config, "_saved_cf_tab_count")
|
1579
|
+
and sb_config._saved_cf_tab_count
|
1580
|
+
and not __is_cdp_swap_needed(driver)
|
1581
|
+
):
|
1582
|
+
driver.uc_open_with_disconnect(driver.current_url, 3.8)
|
1583
|
+
with suppress(Exception):
|
1584
|
+
for i in range(sb_config._saved_cf_tab_count):
|
1585
|
+
pyautogui.press("\t")
|
1586
|
+
time.sleep(0.027)
|
1587
|
+
pyautogui.press(" ")
|
1588
|
+
else:
|
1589
|
+
driver.disconnect()
|
1590
|
+
pyautogui.press(" ")
|
1591
|
+
reconnect_time = (float(constants.UC.RECONNECT_TIME) / 2.0) + 0.6
|
1592
|
+
if IS_LINUX:
|
1593
|
+
reconnect_time = constants.UC.RECONNECT_TIME + 0.2
|
1594
|
+
driver.reconnect(reconnect_time)
|
1595
|
+
|
1596
|
+
|
1597
|
+
def _uc_gui_handle_captcha(driver, frame="iframe", ctype=None):
|
1598
|
+
_uc_gui_handle_captcha_(driver, frame=frame, ctype=ctype)
|
1599
|
+
if (
|
1600
|
+
driver.is_element_present(".footer .clearfix .ray-id")
|
1601
|
+
and not driver.is_element_visible("#challenge-success-text")
|
1602
|
+
):
|
1603
|
+
driver.uc_open_with_reconnect(driver.current_url, 3.8)
|
1604
|
+
_uc_gui_handle_captcha_(driver, frame=frame, ctype=ctype)
|
1605
|
+
|
1606
|
+
|
1607
|
+
def uc_gui_handle_captcha(driver, frame="iframe"):
|
1608
|
+
_uc_gui_handle_captcha(driver, frame=frame, ctype=None)
|
1609
|
+
|
1610
|
+
|
1611
|
+
def uc_gui_handle_cf(driver, frame="iframe"):
|
1612
|
+
_uc_gui_handle_captcha(driver, frame=frame, ctype="cf_t")
|
1613
|
+
|
1614
|
+
|
1615
|
+
def uc_gui_handle_rc(driver, frame="iframe"):
|
1616
|
+
_uc_gui_handle_captcha(driver, frame=frame, ctype="g_rc")
|
1617
|
+
|
1618
|
+
|
1619
|
+
def uc_switch_to_frame(driver, frame="iframe", reconnect_time=None):
|
482
1620
|
from selenium.webdriver.remote.webelement import WebElement
|
483
1621
|
if isinstance(frame, WebElement):
|
484
1622
|
if not reconnect_time:
|
@@ -654,22 +1792,34 @@ def _add_chrome_proxy_extension(
|
|
654
1792
|
):
|
655
1793
|
# Single-threaded
|
656
1794
|
if zip_it:
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
1795
|
+
proxy_zip_lock = fasteners.InterProcessLock(PROXY_ZIP_LOCK)
|
1796
|
+
with proxy_zip_lock:
|
1797
|
+
proxy_helper.create_proxy_ext(
|
1798
|
+
proxy_string, proxy_user, proxy_pass, bypass_list
|
1799
|
+
)
|
1800
|
+
proxy_zip = proxy_helper.PROXY_ZIP_PATH
|
1801
|
+
chrome_options.add_extension(proxy_zip)
|
662
1802
|
else:
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
1803
|
+
proxy_dir_lock = fasteners.InterProcessLock(PROXY_DIR_LOCK)
|
1804
|
+
with proxy_dir_lock:
|
1805
|
+
proxy_helper.create_proxy_ext(
|
1806
|
+
proxy_string,
|
1807
|
+
proxy_user,
|
1808
|
+
proxy_pass,
|
1809
|
+
bypass_list,
|
1810
|
+
zip_it=False,
|
1811
|
+
)
|
1812
|
+
proxy_dir_path = proxy_helper.PROXY_DIR_PATH
|
1813
|
+
chrome_options = add_chrome_ext_dir(
|
1814
|
+
chrome_options, proxy_dir_path
|
1815
|
+
)
|
668
1816
|
else:
|
669
1817
|
# Multi-threaded
|
670
1818
|
if zip_it:
|
671
1819
|
proxy_zip_lock = fasteners.InterProcessLock(PROXY_ZIP_LOCK)
|
672
1820
|
with proxy_zip_lock:
|
1821
|
+
with suppress(Exception):
|
1822
|
+
shared_utils.make_writable(PROXY_ZIP_LOCK)
|
673
1823
|
if multi_proxy:
|
674
1824
|
_set_proxy_filenames()
|
675
1825
|
if not os.path.exists(proxy_helper.PROXY_ZIP_PATH):
|
@@ -681,6 +1831,8 @@ def _add_chrome_proxy_extension(
|
|
681
1831
|
else:
|
682
1832
|
proxy_dir_lock = fasteners.InterProcessLock(PROXY_DIR_LOCK)
|
683
1833
|
with proxy_dir_lock:
|
1834
|
+
with suppress(Exception):
|
1835
|
+
shared_utils.make_writable(PROXY_DIR_LOCK)
|
684
1836
|
if multi_proxy:
|
685
1837
|
_set_proxy_filenames()
|
686
1838
|
if not os.path.exists(proxy_helper.PROXY_DIR_PATH):
|
@@ -689,7 +1841,7 @@ def _add_chrome_proxy_extension(
|
|
689
1841
|
proxy_user,
|
690
1842
|
proxy_pass,
|
691
1843
|
bypass_list,
|
692
|
-
False,
|
1844
|
+
zip_it=False,
|
693
1845
|
)
|
694
1846
|
chrome_options = add_chrome_ext_dir(
|
695
1847
|
chrome_options, proxy_helper.PROXY_DIR_PATH
|
@@ -706,6 +1858,8 @@ def is_using_uc(undetectable, browser_name):
|
|
706
1858
|
def _unzip_to_new_folder(zip_file, folder):
|
707
1859
|
proxy_dir_lock = fasteners.InterProcessLock(PROXY_DIR_LOCK)
|
708
1860
|
with proxy_dir_lock:
|
1861
|
+
with suppress(Exception):
|
1862
|
+
shared_utils.make_writable(PROXY_DIR_LOCK)
|
709
1863
|
if not os.path.exists(folder):
|
710
1864
|
import zipfile
|
711
1865
|
zip_ref = zipfile.ZipFile(zip_file, "r")
|
@@ -765,6 +1919,7 @@ def _set_chrome_options(
|
|
765
1919
|
multi_proxy,
|
766
1920
|
user_agent,
|
767
1921
|
recorder_ext,
|
1922
|
+
disable_cookies,
|
768
1923
|
disable_js,
|
769
1924
|
disable_csp,
|
770
1925
|
enable_ws,
|
@@ -776,6 +1931,7 @@ def _set_chrome_options(
|
|
776
1931
|
log_cdp_events,
|
777
1932
|
no_sandbox,
|
778
1933
|
disable_gpu,
|
1934
|
+
headless1,
|
779
1935
|
headless2,
|
780
1936
|
incognito,
|
781
1937
|
guest_mode,
|
@@ -812,11 +1968,12 @@ def _set_chrome_options(
|
|
812
1968
|
chrome_options = webdriver.edge.options.Options()
|
813
1969
|
prefs = {}
|
814
1970
|
prefs["download.default_directory"] = downloads_path
|
815
|
-
prefs["local_discovery.notifications_enabled"] = False
|
816
|
-
prefs["credentials_enable_service"] = False
|
817
|
-
prefs["download.prompt_for_download"] = False
|
818
1971
|
prefs["download.directory_upgrade"] = True
|
819
|
-
prefs["
|
1972
|
+
prefs["download.prompt_for_download"] = False
|
1973
|
+
prefs["credentials_enable_service"] = False
|
1974
|
+
prefs["local_discovery.notifications_enabled"] = False
|
1975
|
+
prefs["safebrowsing.enabled"] = False # Prevent PW "data breach" pop-ups
|
1976
|
+
prefs["safebrowsing.disable_download_protection"] = True
|
820
1977
|
prefs["omnibox-max-zero-suggest-matches"] = 0
|
821
1978
|
prefs["omnibox-use-existing-autocomplete-client"] = 0
|
822
1979
|
prefs["omnibox-trending-zero-prefix-suggestions-on-ntp"] = 0
|
@@ -827,12 +1984,12 @@ def _set_chrome_options(
|
|
827
1984
|
prefs["omnibox-zero-suggest-prefetching-on-srp"] = 0
|
828
1985
|
prefs["omnibox-zero-suggest-prefetching-on-web"] = 0
|
829
1986
|
prefs["omnibox-zero-suggest-in-memory-caching"] = 0
|
830
|
-
prefs["default_content_setting_values.notifications"] = 0
|
831
1987
|
prefs["content_settings.exceptions.automatic_downloads.*.setting"] = 1
|
832
|
-
prefs["
|
1988
|
+
prefs["default_content_setting_values.notifications"] = 0
|
833
1989
|
prefs["default_content_settings.popups"] = 0
|
834
1990
|
prefs["managed_default_content_settings.popups"] = 0
|
835
1991
|
prefs["profile.password_manager_enabled"] = False
|
1992
|
+
prefs["profile.password_manager_leak_detection"] = False
|
836
1993
|
prefs["profile.default_content_setting_values.notifications"] = 2
|
837
1994
|
prefs["profile.default_content_settings.popups"] = 0
|
838
1995
|
prefs["profile.managed_default_content_settings.popups"] = 0
|
@@ -841,6 +1998,8 @@ def _set_chrome_options(
|
|
841
1998
|
prefs["intl.accept_languages"] = locale_code
|
842
1999
|
if block_images:
|
843
2000
|
prefs["profile.managed_default_content_settings.images"] = 2
|
2001
|
+
if disable_cookies:
|
2002
|
+
prefs["profile.default_content_setting_values.cookies"] = 2
|
844
2003
|
if disable_js:
|
845
2004
|
prefs["profile.managed_default_content_settings.javascript"] = 2
|
846
2005
|
if do_not_track:
|
@@ -878,7 +2037,7 @@ def _set_chrome_options(
|
|
878
2037
|
if (
|
879
2038
|
isinstance(device_width, int)
|
880
2039
|
and isinstance(device_height, int)
|
881
|
-
and isinstance(device_pixel_ratio, int)
|
2040
|
+
and isinstance(device_pixel_ratio, (int, float))
|
882
2041
|
):
|
883
2042
|
device_metrics["width"] = device_width
|
884
2043
|
device_metrics["height"] = device_height
|
@@ -893,18 +2052,49 @@ def _set_chrome_options(
|
|
893
2052
|
chrome_options.add_experimental_option(
|
894
2053
|
"mobileEmulation", emulator_settings
|
895
2054
|
)
|
2055
|
+
# Handle Window Position
|
2056
|
+
if (headless or headless2) and IS_WINDOWS:
|
2057
|
+
# https://stackoverflow.com/a/78999088/7058266
|
2058
|
+
chrome_options.add_argument("--window-position=-2400,-2400")
|
2059
|
+
else:
|
2060
|
+
if (
|
2061
|
+
hasattr(settings, "WINDOW_START_X")
|
2062
|
+
and isinstance(settings.WINDOW_START_X, int)
|
2063
|
+
and hasattr(settings, "WINDOW_START_Y")
|
2064
|
+
and isinstance(settings.WINDOW_START_Y, int)
|
2065
|
+
):
|
2066
|
+
chrome_options.add_argument(
|
2067
|
+
"--window-position=%s,%s" % (
|
2068
|
+
settings.WINDOW_START_X, settings.WINDOW_START_Y
|
2069
|
+
)
|
2070
|
+
)
|
2071
|
+
# Handle Window Size
|
896
2072
|
if headless or headless2:
|
897
|
-
|
898
|
-
"
|
899
|
-
|
2073
|
+
if (
|
2074
|
+
hasattr(settings, "HEADLESS_START_WIDTH")
|
2075
|
+
and isinstance(settings.HEADLESS_START_WIDTH, int)
|
2076
|
+
and hasattr(settings, "HEADLESS_START_HEIGHT")
|
2077
|
+
and isinstance(settings.HEADLESS_START_HEIGHT, int)
|
2078
|
+
):
|
2079
|
+
chrome_options.add_argument(
|
2080
|
+
"--window-size=%s,%s" % (
|
2081
|
+
settings.HEADLESS_START_WIDTH,
|
2082
|
+
settings.HEADLESS_START_HEIGHT,
|
2083
|
+
)
|
900
2084
|
)
|
901
|
-
)
|
902
2085
|
else:
|
903
|
-
|
904
|
-
"
|
905
|
-
|
2086
|
+
if (
|
2087
|
+
hasattr(settings, "CHROME_START_WIDTH")
|
2088
|
+
and isinstance(settings.CHROME_START_WIDTH, int)
|
2089
|
+
and hasattr(settings, "CHROME_START_HEIGHT")
|
2090
|
+
and isinstance(settings.CHROME_START_HEIGHT, int)
|
2091
|
+
):
|
2092
|
+
chrome_options.add_argument(
|
2093
|
+
"--window-size=%s,%s" % (
|
2094
|
+
settings.CHROME_START_WIDTH,
|
2095
|
+
settings.CHROME_START_HEIGHT,
|
2096
|
+
)
|
906
2097
|
)
|
907
|
-
)
|
908
2098
|
if (
|
909
2099
|
not proxy_auth
|
910
2100
|
and not disable_csp
|
@@ -963,7 +2153,10 @@ def _set_chrome_options(
|
|
963
2153
|
pass # Processed After Version Check
|
964
2154
|
elif headless:
|
965
2155
|
if not undetectable:
|
966
|
-
|
2156
|
+
if headless1:
|
2157
|
+
chrome_options.add_argument("--headless=old")
|
2158
|
+
else:
|
2159
|
+
chrome_options.add_argument("--headless")
|
967
2160
|
if undetectable and servername and servername != "localhost":
|
968
2161
|
# The Grid Node will need Chrome 109 or newer
|
969
2162
|
chrome_options.add_argument("--headless=new")
|
@@ -1045,7 +2238,10 @@ def _set_chrome_options(
|
|
1045
2238
|
chrome_options.add_argument("--ignore-certificate-errors")
|
1046
2239
|
if not enable_ws:
|
1047
2240
|
chrome_options.add_argument("--disable-web-security")
|
1048
|
-
if
|
2241
|
+
if (
|
2242
|
+
IS_LINUX
|
2243
|
+
or (IS_MAC and not is_using_uc(undetectable, browser_name))
|
2244
|
+
):
|
1049
2245
|
chrome_options.add_argument("--no-sandbox")
|
1050
2246
|
if remote_debug:
|
1051
2247
|
# To access the Debugger, go to: chrome://inspect/#devices
|
@@ -1077,10 +2273,18 @@ def _set_chrome_options(
|
|
1077
2273
|
binary_loc = detect_b_ver.get_binary_location(br_app, True)
|
1078
2274
|
if os.path.exists(binary_loc):
|
1079
2275
|
binary_location = binary_loc
|
2276
|
+
elif os.path.exists("/usr/bin/google-chrome-stable"):
|
2277
|
+
binary_location = "/usr/bin/google-chrome-stable"
|
2278
|
+
elif os.path.exists("/usr/bin/google-chrome"):
|
2279
|
+
binary_location = "/usr/bin/google-chrome"
|
1080
2280
|
extra_disabled_features = []
|
1081
2281
|
if chromium_arg:
|
1082
|
-
# Can be a comma-separated list of Chromium args
|
1083
|
-
chromium_arg_list =
|
2282
|
+
# Can be a comma-separated list of Chromium args or a list
|
2283
|
+
chromium_arg_list = None
|
2284
|
+
if isinstance(chromium_arg, (list, tuple)):
|
2285
|
+
chromium_arg_list = chromium_arg
|
2286
|
+
else:
|
2287
|
+
chromium_arg_list = chromium_arg.split(",")
|
1084
2288
|
for chromium_arg_item in chromium_arg_list:
|
1085
2289
|
chromium_arg_item = chromium_arg_item.strip()
|
1086
2290
|
if not chromium_arg_item.startswith("--"):
|
@@ -1089,13 +2293,11 @@ def _set_chrome_options(
|
|
1089
2293
|
else:
|
1090
2294
|
chromium_arg_item = "--" + chromium_arg_item
|
1091
2295
|
if "remote-debugging-port=" in chromium_arg_item:
|
1092
|
-
|
2296
|
+
with suppress(Exception):
|
1093
2297
|
# Extra processing for UC Mode
|
1094
2298
|
chrome_options._remote_debugging_port = int(
|
1095
2299
|
chromium_arg_item.split("remote-debugging-port=")[1]
|
1096
2300
|
)
|
1097
|
-
except Exception:
|
1098
|
-
pass
|
1099
2301
|
if "set-binary" in chromium_arg_item and not binary_location:
|
1100
2302
|
br_app = "google-chrome"
|
1101
2303
|
binary_loc = detect_b_ver.get_binary_location(
|
@@ -1114,6 +2316,8 @@ def _set_chrome_options(
|
|
1114
2316
|
chrome_options.add_argument("--auto-open-devtools-for-tabs")
|
1115
2317
|
if user_agent:
|
1116
2318
|
chrome_options.add_argument("--user-agent=%s" % user_agent)
|
2319
|
+
chrome_options.add_argument("--safebrowsing-disable-download-protection")
|
2320
|
+
chrome_options.add_argument("--disable-search-engine-choice-screen")
|
1117
2321
|
chrome_options.add_argument("--disable-browser-side-navigation")
|
1118
2322
|
chrome_options.add_argument("--disable-save-password-bubble")
|
1119
2323
|
chrome_options.add_argument("--disable-single-click-autofill")
|
@@ -1134,30 +2338,31 @@ def _set_chrome_options(
|
|
1134
2338
|
chrome_options.add_argument("--ash-no-nudges")
|
1135
2339
|
chrome_options.add_argument("--no-crash-upload")
|
1136
2340
|
chrome_options.add_argument("--deny-permission-prompts")
|
2341
|
+
chrome_options.add_argument(
|
2342
|
+
'--simulate-outdated-no-au="Tue, 31 Dec 2099 23:59:59 GMT"'
|
2343
|
+
)
|
2344
|
+
chrome_options.add_argument("--disable-ipc-flooding-protection")
|
2345
|
+
chrome_options.add_argument("--disable-password-generation")
|
2346
|
+
chrome_options.add_argument("--disable-domain-reliability")
|
2347
|
+
chrome_options.add_argument("--disable-breakpad")
|
1137
2348
|
included_disabled_features = []
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
included_disabled_features
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
included_disabled_features.append("DownloadBubbleV2")
|
1156
|
-
for item in extra_disabled_features:
|
1157
|
-
if item not in included_disabled_features:
|
1158
|
-
included_disabled_features.append(item)
|
1159
|
-
d_f_string = ",".join(included_disabled_features)
|
1160
|
-
chrome_options.add_argument("--disable-features=%s" % d_f_string)
|
2349
|
+
included_disabled_features.append("OptimizationHints")
|
2350
|
+
included_disabled_features.append("OptimizationHintsFetching")
|
2351
|
+
included_disabled_features.append("Translate")
|
2352
|
+
included_disabled_features.append("OptimizationTargetPrediction")
|
2353
|
+
included_disabled_features.append("OptimizationGuideModelDownloading")
|
2354
|
+
included_disabled_features.append("DownloadBubble")
|
2355
|
+
included_disabled_features.append("DownloadBubbleV2")
|
2356
|
+
included_disabled_features.append("InsecureDownloadWarnings")
|
2357
|
+
included_disabled_features.append("InterestFeedContentSuggestions")
|
2358
|
+
included_disabled_features.append("PrivacySandboxSettings4")
|
2359
|
+
included_disabled_features.append("SidePanelPinning")
|
2360
|
+
included_disabled_features.append("UserAgentClientHint")
|
2361
|
+
for item in extra_disabled_features:
|
2362
|
+
if item not in included_disabled_features:
|
2363
|
+
included_disabled_features.append(item)
|
2364
|
+
d_f_string = ",".join(included_disabled_features)
|
2365
|
+
chrome_options.add_argument("--disable-features=%s" % d_f_string)
|
1161
2366
|
if (
|
1162
2367
|
is_using_uc(undetectable, browser_name)
|
1163
2368
|
and (
|
@@ -1165,8 +2370,14 @@ def _set_chrome_options(
|
|
1165
2370
|
or IS_LINUX # switches to Xvfb (non-headless)
|
1166
2371
|
)
|
1167
2372
|
):
|
2373
|
+
chrome_options.add_argument("--no-pings")
|
2374
|
+
chrome_options.add_argument("--homepage=chrome://version/")
|
2375
|
+
chrome_options.add_argument("--animation-duration-scale=0")
|
2376
|
+
chrome_options.add_argument("--wm-window-animations-disabled")
|
2377
|
+
chrome_options.add_argument("--enable-privacy-sandbox-ads-apis")
|
2378
|
+
chrome_options.add_argument("--disable-background-timer-throttling")
|
2379
|
+
# Prevent new tabs opened by Selenium from being blocked:
|
1168
2380
|
chrome_options.add_argument("--disable-popup-blocking")
|
1169
|
-
chrome_options.add_argument("--homepage=chrome://new-tab-page/")
|
1170
2381
|
# Skip remaining options that trigger anti-bot services
|
1171
2382
|
return chrome_options
|
1172
2383
|
chrome_options.add_argument("--test-type")
|
@@ -1193,10 +2404,12 @@ def _set_firefox_options(
|
|
1193
2404
|
proxy_bypass_list,
|
1194
2405
|
proxy_pac_url,
|
1195
2406
|
user_agent,
|
2407
|
+
disable_cookies,
|
1196
2408
|
disable_js,
|
1197
2409
|
disable_csp,
|
1198
2410
|
firefox_arg,
|
1199
2411
|
firefox_pref,
|
2412
|
+
external_pdf,
|
1200
2413
|
):
|
1201
2414
|
blank_p = "about:blank"
|
1202
2415
|
options = webdriver.FirefoxOptions()
|
@@ -1208,7 +2421,6 @@ def _set_firefox_options(
|
|
1208
2421
|
options.set_preference("browser.newtab.url", blank_p)
|
1209
2422
|
options.set_preference("trailhead.firstrun.branches", "nofirstrun-empty")
|
1210
2423
|
options.set_preference("browser.aboutwelcome.enabled", False)
|
1211
|
-
options.set_preference("pdfjs.disabled", True)
|
1212
2424
|
options.set_preference("app.update.auto", False)
|
1213
2425
|
options.set_preference("app.update.enabled", False)
|
1214
2426
|
options.set_preference("browser.formfill.enable", False)
|
@@ -1216,8 +2428,6 @@ def _set_firefox_options(
|
|
1216
2428
|
options.set_preference("dom.webnotifications.enabled", False)
|
1217
2429
|
options.set_preference("dom.disable_beforeunload", True)
|
1218
2430
|
options.set_preference("browser.contentblocking.database.enabled", True)
|
1219
|
-
options.set_preference("extensions.allowPrivateBrowsingByDefault", True)
|
1220
|
-
options.set_preference("extensions.PrivateBrowsing.notification", False)
|
1221
2431
|
options.set_preference("extensions.systemAddon.update.enabled", False)
|
1222
2432
|
options.set_preference("extensions.update.autoUpdateDefault", False)
|
1223
2433
|
options.set_preference("extensions.update.enabled", False)
|
@@ -1266,6 +2476,8 @@ def _set_firefox_options(
|
|
1266
2476
|
"security.mixed_content.block_active_content", False
|
1267
2477
|
)
|
1268
2478
|
options.set_preference("security.warn_submit_insecure", False)
|
2479
|
+
if disable_cookies:
|
2480
|
+
options.set_preference("network.cookie.cookieBehavior", 2)
|
1269
2481
|
if disable_js:
|
1270
2482
|
options.set_preference("javascript.enabled", False)
|
1271
2483
|
if settings.DISABLE_CSP_ON_FIREFOX or disable_csp:
|
@@ -1293,22 +2505,27 @@ def _set_firefox_options(
|
|
1293
2505
|
options.set_preference(
|
1294
2506
|
"browser.helperApps.neverAsk.saveToDisk",
|
1295
2507
|
(
|
1296
|
-
"application/pdf,
|
1297
|
-
"text/csv,
|
1298
|
-
"text/octet-stream,
|
1299
|
-
"application/"
|
1300
|
-
"
|
2508
|
+
"application/pdf,application/zip,application/octet-stream,"
|
2509
|
+
"text/csv,text/xml,application/xml,text/plain,application/json,"
|
2510
|
+
"text/octet-stream,application/x-gzip,application/x-tar,"
|
2511
|
+
"application/java-archive,text/x-java-source,java,"
|
2512
|
+
"application/javascript,video/jpeg,audio/x-aac,image/svg+xml,"
|
2513
|
+
"application/x-font-woff,application/x-7z-compressed,"
|
2514
|
+
"application/mp4,video/mp4,audio/mp4,video/x-msvideo,"
|
2515
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
1301
2516
|
),
|
1302
2517
|
)
|
2518
|
+
if external_pdf:
|
2519
|
+
options.set_preference("pdfjs.disabled", True)
|
2520
|
+
else:
|
2521
|
+
options.set_preference("pdfjs.disabled", False)
|
1303
2522
|
if firefox_arg:
|
1304
2523
|
# Can be a comma-separated list of Firefox args
|
1305
2524
|
firefox_arg_list = firefox_arg.split(",")
|
1306
2525
|
for firefox_arg_item in firefox_arg_list:
|
1307
2526
|
firefox_arg_item = firefox_arg_item.strip()
|
1308
|
-
if not firefox_arg_item.startswith("
|
1309
|
-
if firefox_arg_item.
|
1310
|
-
firefox_arg_item = "-" + firefox_arg_item
|
1311
|
-
else:
|
2527
|
+
if not firefox_arg_item.startswith("-"):
|
2528
|
+
if firefox_arg_item.count(os.sep) == 0:
|
1312
2529
|
firefox_arg_item = "--" + firefox_arg_item
|
1313
2530
|
if len(firefox_arg_item) >= 3:
|
1314
2531
|
options.add_argument(firefox_arg_item)
|
@@ -1340,7 +2557,7 @@ def _set_firefox_options(
|
|
1340
2557
|
f_pref_value = False
|
1341
2558
|
elif f_pref_value.isdigit():
|
1342
2559
|
f_pref_value = int(f_pref_value)
|
1343
|
-
elif f_pref_value.
|
2560
|
+
elif f_pref_value.replace(".", "", 1).isdigit():
|
1344
2561
|
f_pref_value = float(f_pref_value)
|
1345
2562
|
else:
|
1346
2563
|
pass # keep as string
|
@@ -1365,6 +2582,7 @@ def get_driver(
|
|
1365
2582
|
cap_file=None,
|
1366
2583
|
cap_string=None,
|
1367
2584
|
recorder_ext=False,
|
2585
|
+
disable_cookies=False,
|
1368
2586
|
disable_js=False,
|
1369
2587
|
disable_csp=False,
|
1370
2588
|
enable_ws=False,
|
@@ -1376,6 +2594,7 @@ def get_driver(
|
|
1376
2594
|
log_cdp_events=False,
|
1377
2595
|
no_sandbox=False,
|
1378
2596
|
disable_gpu=False,
|
2597
|
+
headless1=False,
|
1379
2598
|
headless2=False,
|
1380
2599
|
incognito=False,
|
1381
2600
|
guest_mode=False,
|
@@ -1524,6 +2743,7 @@ def get_driver(
|
|
1524
2743
|
headless
|
1525
2744
|
and (
|
1526
2745
|
proxy_auth
|
2746
|
+
or disable_cookies
|
1527
2747
|
or disable_js
|
1528
2748
|
or ad_block_on
|
1529
2749
|
or disable_csp
|
@@ -1578,6 +2798,7 @@ def get_driver(
|
|
1578
2798
|
cap_file,
|
1579
2799
|
cap_string,
|
1580
2800
|
recorder_ext,
|
2801
|
+
disable_cookies,
|
1581
2802
|
disable_js,
|
1582
2803
|
disable_csp,
|
1583
2804
|
enable_ws,
|
@@ -1589,6 +2810,7 @@ def get_driver(
|
|
1589
2810
|
log_cdp_events,
|
1590
2811
|
no_sandbox,
|
1591
2812
|
disable_gpu,
|
2813
|
+
headless1,
|
1592
2814
|
headless2,
|
1593
2815
|
incognito,
|
1594
2816
|
guest_mode,
|
@@ -1634,6 +2856,7 @@ def get_driver(
|
|
1634
2856
|
multi_proxy,
|
1635
2857
|
user_agent,
|
1636
2858
|
recorder_ext,
|
2859
|
+
disable_cookies,
|
1637
2860
|
disable_js,
|
1638
2861
|
disable_csp,
|
1639
2862
|
enable_ws,
|
@@ -1645,6 +2868,7 @@ def get_driver(
|
|
1645
2868
|
log_cdp_events,
|
1646
2869
|
no_sandbox,
|
1647
2870
|
disable_gpu,
|
2871
|
+
headless1,
|
1648
2872
|
headless2,
|
1649
2873
|
incognito,
|
1650
2874
|
guest_mode,
|
@@ -1694,6 +2918,7 @@ def get_remote_driver(
|
|
1694
2918
|
cap_file,
|
1695
2919
|
cap_string,
|
1696
2920
|
recorder_ext,
|
2921
|
+
disable_cookies,
|
1697
2922
|
disable_js,
|
1698
2923
|
disable_csp,
|
1699
2924
|
enable_ws,
|
@@ -1705,6 +2930,7 @@ def get_remote_driver(
|
|
1705
2930
|
log_cdp_events,
|
1706
2931
|
no_sandbox,
|
1707
2932
|
disable_gpu,
|
2933
|
+
headless1,
|
1708
2934
|
headless2,
|
1709
2935
|
incognito,
|
1710
2936
|
guest_mode,
|
@@ -1739,14 +2965,28 @@ def get_remote_driver(
|
|
1739
2965
|
pip_find_lock = fasteners.InterProcessLock(
|
1740
2966
|
constants.PipInstall.FINDLOCK
|
1741
2967
|
)
|
1742
|
-
with pip_find_lock:
|
2968
|
+
with pip_find_lock: # Prevent issues with multiple processes
|
2969
|
+
with suppress(Exception):
|
2970
|
+
shared_utils.make_writable(constants.PipInstall.FINDLOCK)
|
1743
2971
|
try:
|
1744
2972
|
from seleniumwire import webdriver
|
2973
|
+
import blinker
|
2974
|
+
with suppress(Exception):
|
2975
|
+
use_blinker_ver = constants.SeleniumWire.BLINKER_VER
|
2976
|
+
if blinker.__version__ != use_blinker_ver:
|
2977
|
+
shared_utils.pip_install(
|
2978
|
+
"blinker", version=use_blinker_ver
|
2979
|
+
)
|
2980
|
+
del blinker
|
1745
2981
|
except Exception:
|
2982
|
+
shared_utils.pip_install(
|
2983
|
+
"blinker", version=constants.SeleniumWire.BLINKER_VER
|
2984
|
+
)
|
1746
2985
|
shared_utils.pip_install(
|
1747
2986
|
"selenium-wire", version=constants.SeleniumWire.VER
|
1748
2987
|
)
|
1749
2988
|
from seleniumwire import webdriver
|
2989
|
+
warnings.simplefilter("ignore", category=DeprecationWarning)
|
1750
2990
|
else:
|
1751
2991
|
from selenium import webdriver
|
1752
2992
|
|
@@ -1817,6 +3057,7 @@ def get_remote_driver(
|
|
1817
3057
|
multi_proxy,
|
1818
3058
|
user_agent,
|
1819
3059
|
recorder_ext,
|
3060
|
+
disable_cookies,
|
1820
3061
|
disable_js,
|
1821
3062
|
disable_csp,
|
1822
3063
|
enable_ws,
|
@@ -1828,6 +3069,7 @@ def get_remote_driver(
|
|
1828
3069
|
log_cdp_events,
|
1829
3070
|
no_sandbox,
|
1830
3071
|
disable_gpu,
|
3072
|
+
headless1,
|
1831
3073
|
headless2,
|
1832
3074
|
incognito,
|
1833
3075
|
guest_mode,
|
@@ -1911,10 +3153,12 @@ def get_remote_driver(
|
|
1911
3153
|
proxy_bypass_list,
|
1912
3154
|
proxy_pac_url,
|
1913
3155
|
user_agent,
|
3156
|
+
disable_cookies,
|
1914
3157
|
disable_js,
|
1915
3158
|
disable_csp,
|
1916
3159
|
firefox_arg,
|
1917
3160
|
firefox_pref,
|
3161
|
+
external_pdf,
|
1918
3162
|
)
|
1919
3163
|
capabilities = webdriver.FirefoxOptions().to_capabilities()
|
1920
3164
|
capabilities["marionette"] = True
|
@@ -1989,6 +3233,7 @@ def get_remote_driver(
|
|
1989
3233
|
multi_proxy,
|
1990
3234
|
user_agent,
|
1991
3235
|
recorder_ext,
|
3236
|
+
disable_cookies,
|
1992
3237
|
disable_js,
|
1993
3238
|
disable_csp,
|
1994
3239
|
enable_ws,
|
@@ -2000,6 +3245,7 @@ def get_remote_driver(
|
|
2000
3245
|
log_cdp_events,
|
2001
3246
|
no_sandbox,
|
2002
3247
|
disable_gpu,
|
3248
|
+
headless1,
|
2003
3249
|
headless2,
|
2004
3250
|
incognito,
|
2005
3251
|
guest_mode,
|
@@ -2108,6 +3354,7 @@ def get_local_driver(
|
|
2108
3354
|
multi_proxy,
|
2109
3355
|
user_agent,
|
2110
3356
|
recorder_ext,
|
3357
|
+
disable_cookies,
|
2111
3358
|
disable_js,
|
2112
3359
|
disable_csp,
|
2113
3360
|
enable_ws,
|
@@ -2119,6 +3366,7 @@ def get_local_driver(
|
|
2119
3366
|
log_cdp_events,
|
2120
3367
|
no_sandbox,
|
2121
3368
|
disable_gpu,
|
3369
|
+
headless1,
|
2122
3370
|
headless2,
|
2123
3371
|
incognito,
|
2124
3372
|
guest_mode,
|
@@ -2153,17 +3401,31 @@ def get_local_driver(
|
|
2153
3401
|
downloads_path = DOWNLOADS_FOLDER
|
2154
3402
|
b_path = binary_location
|
2155
3403
|
if use_wire:
|
2156
|
-
|
2157
|
-
constants.
|
3404
|
+
pip_find_lock = fasteners.InterProcessLock(
|
3405
|
+
constants.PipInstall.FINDLOCK
|
2158
3406
|
)
|
2159
|
-
with
|
3407
|
+
with pip_find_lock: # Prevent issues with multiple processes
|
3408
|
+
with suppress(Exception):
|
3409
|
+
shared_utils.make_writable(constants.PipInstall.FINDLOCK)
|
2160
3410
|
try:
|
2161
3411
|
from seleniumwire import webdriver
|
3412
|
+
import blinker
|
3413
|
+
with suppress(Exception):
|
3414
|
+
use_blinker_ver = constants.SeleniumWire.BLINKER_VER
|
3415
|
+
if blinker.__version__ != use_blinker_ver:
|
3416
|
+
shared_utils.pip_install(
|
3417
|
+
"blinker", version=use_blinker_ver
|
3418
|
+
)
|
3419
|
+
del blinker
|
2162
3420
|
except Exception:
|
3421
|
+
shared_utils.pip_install(
|
3422
|
+
"blinker", version=constants.SeleniumWire.BLINKER_VER
|
3423
|
+
)
|
2163
3424
|
shared_utils.pip_install(
|
2164
3425
|
"selenium-wire", version=constants.SeleniumWire.VER
|
2165
3426
|
)
|
2166
3427
|
from seleniumwire import webdriver
|
3428
|
+
warnings.simplefilter("ignore", category=DeprecationWarning)
|
2167
3429
|
else:
|
2168
3430
|
from selenium import webdriver
|
2169
3431
|
|
@@ -2176,10 +3438,12 @@ def get_local_driver(
|
|
2176
3438
|
proxy_bypass_list,
|
2177
3439
|
proxy_pac_url,
|
2178
3440
|
user_agent,
|
3441
|
+
disable_cookies,
|
2179
3442
|
disable_js,
|
2180
3443
|
disable_csp,
|
2181
3444
|
firefox_arg,
|
2182
3445
|
firefox_pref,
|
3446
|
+
external_pdf,
|
2183
3447
|
)
|
2184
3448
|
if LOCAL_GECKODRIVER and os.path.exists(LOCAL_GECKODRIVER):
|
2185
3449
|
try:
|
@@ -2206,6 +3470,10 @@ def get_local_driver(
|
|
2206
3470
|
constants.MultiBrowser.DRIVER_FIXING_LOCK
|
2207
3471
|
)
|
2208
3472
|
with geckodriver_fixing_lock:
|
3473
|
+
with suppress(Exception):
|
3474
|
+
shared_utils.make_writable(
|
3475
|
+
constants.MultiBrowser.DRIVER_FIXING_LOCK
|
3476
|
+
)
|
2209
3477
|
if not geckodriver_on_path():
|
2210
3478
|
sys_args = sys.argv # Save a copy of sys args
|
2211
3479
|
log_d(
|
@@ -2232,11 +3500,13 @@ def get_local_driver(
|
|
2232
3500
|
or "Process unexpectedly closed" in str(e)
|
2233
3501
|
or "Failed to read marionette port" in str(e)
|
2234
3502
|
or "A connection attempt failed" in str(e)
|
3503
|
+
or "Expected browser binary" in str(e)
|
2235
3504
|
or hasattr(e, "msg") and (
|
2236
3505
|
"geckodriver unexpectedly exited" in e.msg
|
2237
3506
|
or "Process unexpectedly closed" in e.msg
|
2238
3507
|
or "Failed to read marionette port" in e.msg
|
2239
3508
|
or "A connection attempt failed" in e.msg
|
3509
|
+
or "Expected browser binary" in e.msg
|
2240
3510
|
)
|
2241
3511
|
):
|
2242
3512
|
time.sleep(0.1)
|
@@ -2272,11 +3542,13 @@ def get_local_driver(
|
|
2272
3542
|
or "Process unexpectedly closed" in str(e)
|
2273
3543
|
or "Failed to read marionette port" in str(e)
|
2274
3544
|
or "A connection attempt failed" in str(e)
|
3545
|
+
or "Expected browser binary" in str(e)
|
2275
3546
|
or hasattr(e, "msg") and (
|
2276
3547
|
"geckodriver unexpectedly exited" in e.msg
|
2277
3548
|
or "Process unexpectedly closed" in e.msg
|
2278
3549
|
or "Failed to read marionette port" in e.msg
|
2279
3550
|
or "A connection attempt failed" in e.msg
|
3551
|
+
or "Expected browser binary" in e.msg
|
2280
3552
|
)
|
2281
3553
|
):
|
2282
3554
|
time.sleep(0.1)
|
@@ -2367,11 +3639,12 @@ def get_local_driver(
|
|
2367
3639
|
elif browser_name == constants.Browser.EDGE:
|
2368
3640
|
prefs = {
|
2369
3641
|
"download.default_directory": downloads_path,
|
2370
|
-
"local_discovery.notifications_enabled": False,
|
2371
|
-
"credentials_enable_service": False,
|
2372
|
-
"download.prompt_for_download": False,
|
2373
3642
|
"download.directory_upgrade": True,
|
2374
|
-
"
|
3643
|
+
"download.prompt_for_download": False,
|
3644
|
+
"credentials_enable_service": False,
|
3645
|
+
"local_discovery.notifications_enabled": False,
|
3646
|
+
"safebrowsing.disable_download_protection": True,
|
3647
|
+
"safebrowsing.enabled": False, # Prevent PW "data breach" pop-ups
|
2375
3648
|
"omnibox-max-zero-suggest-matches": 0,
|
2376
3649
|
"omnibox-use-existing-autocomplete-client": 0,
|
2377
3650
|
"omnibox-trending-zero-prefix-suggestions-on-ntp": 0,
|
@@ -2382,12 +3655,12 @@ def get_local_driver(
|
|
2382
3655
|
"omnibox-zero-suggest-prefetching-on-srp": 0,
|
2383
3656
|
"omnibox-zero-suggest-prefetching-on-web": 0,
|
2384
3657
|
"omnibox-zero-suggest-in-memory-caching": 0,
|
2385
|
-
"
|
3658
|
+
"content_settings.exceptions.automatic_downloads.*.setting": 1,
|
2386
3659
|
"default_content_setting_values.notifications": 0,
|
2387
3660
|
"default_content_settings.popups": 0,
|
2388
3661
|
"managed_default_content_settings.popups": 0,
|
2389
|
-
"content_settings.exceptions.automatic_downloads.*.setting": 1,
|
2390
3662
|
"profile.password_manager_enabled": False,
|
3663
|
+
"profile.password_manager_leak_detection": False,
|
2391
3664
|
"profile.default_content_setting_values.notifications": 2,
|
2392
3665
|
"profile.default_content_settings.popups": 0,
|
2393
3666
|
"profile.managed_default_content_settings.popups": 0,
|
@@ -2440,7 +3713,7 @@ def get_local_driver(
|
|
2440
3713
|
edge_driver_version = None
|
2441
3714
|
edgedriver_upgrade_needed = False
|
2442
3715
|
if os.path.exists(LOCAL_EDGEDRIVER):
|
2443
|
-
|
3716
|
+
with suppress(Exception):
|
2444
3717
|
output = subprocess.check_output(
|
2445
3718
|
'"%s" --version' % LOCAL_EDGEDRIVER, shell=True
|
2446
3719
|
)
|
@@ -2466,8 +3739,6 @@ def get_local_driver(
|
|
2466
3739
|
edge_driver_version = output
|
2467
3740
|
if driver_version == "keep":
|
2468
3741
|
driver_version = edge_driver_version
|
2469
|
-
except Exception:
|
2470
|
-
pass
|
2471
3742
|
use_version = find_edgedriver_version_to_use(
|
2472
3743
|
use_version, driver_version
|
2473
3744
|
)
|
@@ -2505,6 +3776,10 @@ def get_local_driver(
|
|
2505
3776
|
constants.MultiBrowser.DRIVER_FIXING_LOCK
|
2506
3777
|
)
|
2507
3778
|
with edgedriver_fixing_lock:
|
3779
|
+
with suppress(Exception):
|
3780
|
+
shared_utils.make_writable(
|
3781
|
+
constants.MultiBrowser.DRIVER_FIXING_LOCK
|
3782
|
+
)
|
2508
3783
|
msg = "Microsoft Edge Driver not found."
|
2509
3784
|
if edgedriver_upgrade_needed:
|
2510
3785
|
msg = "Microsoft Edge Driver update needed."
|
@@ -2530,6 +3805,8 @@ def get_local_driver(
|
|
2530
3805
|
prefs["intl.accept_languages"] = locale_code
|
2531
3806
|
if block_images:
|
2532
3807
|
prefs["profile.managed_default_content_settings.images"] = 2
|
3808
|
+
if disable_cookies:
|
3809
|
+
prefs["profile.default_content_setting_values.cookies"] = 2
|
2533
3810
|
if disable_js:
|
2534
3811
|
prefs["profile.managed_default_content_settings.javascript"] = 2
|
2535
3812
|
if do_not_track:
|
@@ -2571,7 +3848,7 @@ def get_local_driver(
|
|
2571
3848
|
edge_options.add_argument("--headless=new")
|
2572
3849
|
elif headless and undetectable:
|
2573
3850
|
# (For later: UC Mode doesn't support Edge now)
|
2574
|
-
|
3851
|
+
with suppress(Exception):
|
2575
3852
|
if int(use_version) >= 109:
|
2576
3853
|
edge_options.add_argument("--headless=new")
|
2577
3854
|
elif (
|
@@ -2581,18 +3858,22 @@ def get_local_driver(
|
|
2581
3858
|
edge_options.add_argument("--headless=chrome")
|
2582
3859
|
else:
|
2583
3860
|
pass # Will need Xvfb on Linux
|
2584
|
-
except Exception:
|
2585
|
-
pass
|
2586
3861
|
elif headless:
|
2587
|
-
if
|
2588
|
-
|
3862
|
+
if (
|
3863
|
+
"--headless" not in edge_options.arguments
|
3864
|
+
and "--headless=old" not in edge_options.arguments
|
3865
|
+
):
|
3866
|
+
if headless1:
|
3867
|
+
edge_options.add_argument("--headless=old")
|
3868
|
+
else:
|
3869
|
+
edge_options.add_argument("--headless")
|
2589
3870
|
if mobile_emulator and not is_using_uc(undetectable, browser_name):
|
2590
3871
|
emulator_settings = {}
|
2591
3872
|
device_metrics = {}
|
2592
3873
|
if (
|
2593
3874
|
isinstance(device_width, int)
|
2594
3875
|
and isinstance(device_height, int)
|
2595
|
-
and isinstance(device_pixel_ratio, int)
|
3876
|
+
and isinstance(device_pixel_ratio, (int, float))
|
2596
3877
|
):
|
2597
3878
|
device_metrics["width"] = device_width
|
2598
3879
|
device_metrics["height"] = device_height
|
@@ -2607,20 +3888,49 @@ def get_local_driver(
|
|
2607
3888
|
edge_options.add_experimental_option(
|
2608
3889
|
"mobileEmulation", emulator_settings
|
2609
3890
|
)
|
3891
|
+
# Handle Window Position
|
3892
|
+
if (headless or headless2) and IS_WINDOWS:
|
3893
|
+
# https://stackoverflow.com/a/78999088/7058266
|
3894
|
+
edge_options.add_argument("--window-position=-2400,-2400")
|
3895
|
+
else:
|
3896
|
+
if (
|
3897
|
+
hasattr(settings, "WINDOW_START_X")
|
3898
|
+
and isinstance(settings.WINDOW_START_X, int)
|
3899
|
+
and hasattr(settings, "WINDOW_START_Y")
|
3900
|
+
and isinstance(settings.WINDOW_START_Y, int)
|
3901
|
+
):
|
3902
|
+
edge_options.add_argument(
|
3903
|
+
"--window-position=%s,%s" % (
|
3904
|
+
settings.WINDOW_START_X, settings.WINDOW_START_Y
|
3905
|
+
)
|
3906
|
+
)
|
3907
|
+
# Handle Window Size
|
2610
3908
|
if headless or headless2:
|
2611
|
-
|
2612
|
-
"
|
2613
|
-
|
2614
|
-
|
3909
|
+
if (
|
3910
|
+
hasattr(settings, "HEADLESS_START_WIDTH")
|
3911
|
+
and isinstance(settings.HEADLESS_START_WIDTH, int)
|
3912
|
+
and hasattr(settings, "HEADLESS_START_HEIGHT")
|
3913
|
+
and isinstance(settings.HEADLESS_START_HEIGHT, int)
|
3914
|
+
):
|
3915
|
+
edge_options.add_argument(
|
3916
|
+
"--window-size=%s,%s" % (
|
3917
|
+
settings.HEADLESS_START_WIDTH,
|
3918
|
+
settings.HEADLESS_START_HEIGHT,
|
3919
|
+
)
|
2615
3920
|
)
|
2616
|
-
)
|
2617
3921
|
else:
|
2618
|
-
|
2619
|
-
"
|
2620
|
-
|
2621
|
-
|
3922
|
+
if (
|
3923
|
+
hasattr(settings, "CHROME_START_WIDTH")
|
3924
|
+
and isinstance(settings.CHROME_START_WIDTH, int)
|
3925
|
+
and hasattr(settings, "CHROME_START_HEIGHT")
|
3926
|
+
and isinstance(settings.CHROME_START_HEIGHT, int)
|
3927
|
+
):
|
3928
|
+
edge_options.add_argument(
|
3929
|
+
"--window-size=%s,%s" % (
|
3930
|
+
settings.CHROME_START_WIDTH,
|
3931
|
+
settings.CHROME_START_HEIGHT,
|
3932
|
+
)
|
2622
3933
|
)
|
2623
|
-
)
|
2624
3934
|
if user_data_dir and not is_using_uc(undetectable, browser_name):
|
2625
3935
|
abs_path = os.path.abspath(user_data_dir)
|
2626
3936
|
edge_options.add_argument("--user-data-dir=%s" % abs_path)
|
@@ -2641,6 +3951,8 @@ def get_local_driver(
|
|
2641
3951
|
edge_options.add_argument(
|
2642
3952
|
"--disable-autofill-keyboard-accessory-view[8]"
|
2643
3953
|
)
|
3954
|
+
edge_options.add_argument("--safebrowsing-disable-download-protection")
|
3955
|
+
edge_options.add_argument("--disable-search-engine-choice-screen")
|
2644
3956
|
edge_options.add_argument("--disable-browser-side-navigation")
|
2645
3957
|
edge_options.add_argument("--disable-translate")
|
2646
3958
|
if not enable_ws:
|
@@ -2724,7 +4036,10 @@ def get_local_driver(
|
|
2724
4036
|
edge_options.add_argument("--allow-running-insecure-content")
|
2725
4037
|
if user_agent:
|
2726
4038
|
edge_options.add_argument("--user-agent=%s" % user_agent)
|
2727
|
-
if
|
4039
|
+
if (
|
4040
|
+
IS_LINUX
|
4041
|
+
or (IS_MAC and not is_using_uc(undetectable, browser_name))
|
4042
|
+
):
|
2728
4043
|
edge_options.add_argument("--no-sandbox")
|
2729
4044
|
if remote_debug:
|
2730
4045
|
# To access the Debugger, go to: edge://inspect/#devices
|
@@ -2749,7 +4064,11 @@ def get_local_driver(
|
|
2749
4064
|
set_binary = False
|
2750
4065
|
if chromium_arg:
|
2751
4066
|
# Can be a comma-separated list of Chromium args
|
2752
|
-
chromium_arg_list =
|
4067
|
+
chromium_arg_list = None
|
4068
|
+
if isinstance(chromium_arg, (list, tuple)):
|
4069
|
+
chromium_arg_list = chromium_arg
|
4070
|
+
else:
|
4071
|
+
chromium_arg_list = chromium_arg.split(",")
|
2753
4072
|
for chromium_arg_item in chromium_arg_list:
|
2754
4073
|
chromium_arg_item = chromium_arg_item.strip()
|
2755
4074
|
if not chromium_arg_item.startswith("--"):
|
@@ -2766,26 +4085,29 @@ def get_local_driver(
|
|
2766
4085
|
edge_options.add_argument(chromium_arg_item)
|
2767
4086
|
if disable_features:
|
2768
4087
|
extra_disabled_features.extend(disable_features.split(","))
|
4088
|
+
edge_options.add_argument(
|
4089
|
+
'--simulate-outdated-no-au="Tue, 31 Dec 2099 23:59:59 GMT"'
|
4090
|
+
)
|
4091
|
+
edge_options.add_argument("--disable-ipc-flooding-protection")
|
4092
|
+
edge_options.add_argument("--disable-password-generation")
|
4093
|
+
edge_options.add_argument("--disable-domain-reliability")
|
4094
|
+
edge_options.add_argument("--disable-breakpad")
|
2769
4095
|
included_disabled_features = []
|
2770
|
-
|
2771
|
-
|
2772
|
-
|
2773
|
-
|
2774
|
-
|
2775
|
-
|
2776
|
-
|
2777
|
-
|
2778
|
-
|
2779
|
-
|
2780
|
-
|
2781
|
-
included_disabled_features
|
2782
|
-
|
2783
|
-
|
2784
|
-
|
2785
|
-
if item not in included_disabled_features:
|
2786
|
-
included_disabled_features.append(item)
|
2787
|
-
d_f_string = ",".join(included_disabled_features)
|
2788
|
-
edge_options.add_argument("--disable-features=%s" % d_f_string)
|
4096
|
+
included_disabled_features.append("OptimizationHints")
|
4097
|
+
included_disabled_features.append("OptimizationHintsFetching")
|
4098
|
+
included_disabled_features.append("Translate")
|
4099
|
+
included_disabled_features.append("OptimizationTargetPrediction")
|
4100
|
+
included_disabled_features.append("OptimizationGuideModelDownloading")
|
4101
|
+
included_disabled_features.append("InsecureDownloadWarnings")
|
4102
|
+
included_disabled_features.append("InterestFeedContentSuggestions")
|
4103
|
+
included_disabled_features.append("PrivacySandboxSettings4")
|
4104
|
+
included_disabled_features.append("SidePanelPinning")
|
4105
|
+
included_disabled_features.append("UserAgentClientHint")
|
4106
|
+
for item in extra_disabled_features:
|
4107
|
+
if item not in included_disabled_features:
|
4108
|
+
included_disabled_features.append(item)
|
4109
|
+
d_f_string = ",".join(included_disabled_features)
|
4110
|
+
edge_options.add_argument("--disable-features=%s" % d_f_string)
|
2789
4111
|
if (set_binary or IS_LINUX) and not binary_location:
|
2790
4112
|
br_app = "edge"
|
2791
4113
|
binary_loc = detect_b_ver.get_binary_location(br_app)
|
@@ -2840,19 +4162,19 @@ def get_local_driver(
|
|
2840
4162
|
constants.MultiBrowser.DRIVER_FIXING_LOCK
|
2841
4163
|
)
|
2842
4164
|
with edgedriver_fixing_lock:
|
2843
|
-
|
4165
|
+
with suppress(Exception):
|
4166
|
+
shared_utils.make_writable(
|
4167
|
+
constants.MultiBrowser.DRIVER_FIXING_LOCK
|
4168
|
+
)
|
4169
|
+
with suppress(Exception):
|
2844
4170
|
if not _was_driver_repaired():
|
2845
4171
|
_repair_edgedriver(edge_version)
|
2846
4172
|
_mark_driver_repaired()
|
2847
|
-
except Exception:
|
2848
|
-
pass
|
2849
4173
|
else:
|
2850
|
-
|
4174
|
+
with suppress(Exception):
|
2851
4175
|
if not _was_driver_repaired():
|
2852
4176
|
_repair_edgedriver(edge_version)
|
2853
4177
|
_mark_driver_repaired()
|
2854
|
-
except Exception:
|
2855
|
-
pass
|
2856
4178
|
driver = Edge(service=service, options=edge_options)
|
2857
4179
|
return extend_driver(driver)
|
2858
4180
|
elif browser_name == constants.Browser.SAFARI:
|
@@ -2898,6 +4220,7 @@ def get_local_driver(
|
|
2898
4220
|
multi_proxy,
|
2899
4221
|
user_agent,
|
2900
4222
|
recorder_ext,
|
4223
|
+
disable_cookies,
|
2901
4224
|
disable_js,
|
2902
4225
|
disable_csp,
|
2903
4226
|
enable_ws,
|
@@ -2909,6 +4232,7 @@ def get_local_driver(
|
|
2909
4232
|
log_cdp_events,
|
2910
4233
|
no_sandbox,
|
2911
4234
|
disable_gpu,
|
4235
|
+
headless1,
|
2912
4236
|
headless2,
|
2913
4237
|
incognito,
|
2914
4238
|
guest_mode,
|
@@ -3004,7 +4328,7 @@ def get_local_driver(
|
|
3004
4328
|
ch_driver_version = None
|
3005
4329
|
path_chromedriver = chromedriver_on_path()
|
3006
4330
|
if os.path.exists(LOCAL_CHROMEDRIVER):
|
3007
|
-
|
4331
|
+
with suppress(Exception):
|
3008
4332
|
output = subprocess.check_output(
|
3009
4333
|
'"%s" --version' % LOCAL_CHROMEDRIVER, shell=True
|
3010
4334
|
)
|
@@ -3018,8 +4342,6 @@ def get_local_driver(
|
|
3018
4342
|
ch_driver_version = output
|
3019
4343
|
if driver_version == "keep":
|
3020
4344
|
driver_version = ch_driver_version
|
3021
|
-
except Exception:
|
3022
|
-
pass
|
3023
4345
|
elif path_chromedriver:
|
3024
4346
|
try:
|
3025
4347
|
make_driver_executable_if_not(path_chromedriver)
|
@@ -3028,7 +4350,7 @@ def get_local_driver(
|
|
3028
4350
|
"\nWarning: Could not make chromedriver"
|
3029
4351
|
" executable: %s" % e
|
3030
4352
|
)
|
3031
|
-
|
4353
|
+
with suppress(Exception):
|
3032
4354
|
output = subprocess.check_output(
|
3033
4355
|
'"%s" --version' % path_chromedriver, shell=True
|
3034
4356
|
)
|
@@ -3042,8 +4364,6 @@ def get_local_driver(
|
|
3042
4364
|
ch_driver_version = output
|
3043
4365
|
if driver_version == "keep":
|
3044
4366
|
use_version = ch_driver_version
|
3045
|
-
except Exception:
|
3046
|
-
pass
|
3047
4367
|
disable_build_check = True
|
3048
4368
|
uc_driver_version = None
|
3049
4369
|
if is_using_uc(undetectable, browser_name):
|
@@ -3085,8 +4405,14 @@ def get_local_driver(
|
|
3085
4405
|
except Exception:
|
3086
4406
|
pass # Will need Xvfb on Linux
|
3087
4407
|
elif headless:
|
3088
|
-
if
|
3089
|
-
|
4408
|
+
if (
|
4409
|
+
"--headless" not in chrome_options.arguments
|
4410
|
+
and "--headless=old" not in chrome_options.arguments
|
4411
|
+
):
|
4412
|
+
if headless1:
|
4413
|
+
chrome_options.add_argument("--headless=old")
|
4414
|
+
else:
|
4415
|
+
chrome_options.add_argument("--headless")
|
3090
4416
|
if LOCAL_CHROMEDRIVER and os.path.exists(LOCAL_CHROMEDRIVER):
|
3091
4417
|
try:
|
3092
4418
|
make_driver_executable_if_not(LOCAL_CHROMEDRIVER)
|
@@ -3222,6 +4548,10 @@ def get_local_driver(
|
|
3222
4548
|
constants.MultiBrowser.DRIVER_FIXING_LOCK
|
3223
4549
|
)
|
3224
4550
|
with chromedriver_fixing_lock:
|
4551
|
+
with suppress(Exception):
|
4552
|
+
shared_utils.make_writable(
|
4553
|
+
constants.MultiBrowser.DRIVER_FIXING_LOCK
|
4554
|
+
)
|
3225
4555
|
msg = "chromedriver update needed. Getting it now:"
|
3226
4556
|
if not path_chromedriver:
|
3227
4557
|
msg = "chromedriver not found. Getting it now:"
|
@@ -3236,7 +4566,7 @@ def get_local_driver(
|
|
3236
4566
|
if IS_ARM_MAC and use_uc:
|
3237
4567
|
intel_for_uc = True # Use Intel driver for UC Mode
|
3238
4568
|
if os.path.exists(LOCAL_CHROMEDRIVER):
|
3239
|
-
|
4569
|
+
with suppress(Exception):
|
3240
4570
|
output = subprocess.check_output(
|
3241
4571
|
'"%s" --version' % LOCAL_CHROMEDRIVER,
|
3242
4572
|
shell=True,
|
@@ -3249,8 +4579,6 @@ def get_local_driver(
|
|
3249
4579
|
output = full_ch_driver_version.split(".")[0]
|
3250
4580
|
if int(output) >= 2:
|
3251
4581
|
ch_driver_version = output
|
3252
|
-
except Exception:
|
3253
|
-
pass
|
3254
4582
|
if (
|
3255
4583
|
(
|
3256
4584
|
not use_uc
|
@@ -3315,15 +4643,23 @@ def get_local_driver(
|
|
3315
4643
|
constants.MultiBrowser.DRIVER_FIXING_LOCK
|
3316
4644
|
)
|
3317
4645
|
with uc_lock: # Avoid multithreaded issues
|
4646
|
+
with suppress(Exception):
|
4647
|
+
shared_utils.make_writable(
|
4648
|
+
constants.MultiBrowser.DRIVER_FIXING_LOCK
|
4649
|
+
)
|
3318
4650
|
if make_uc_driver_from_chromedriver:
|
3319
4651
|
if os.path.exists(LOCAL_CHROMEDRIVER):
|
3320
|
-
|
3321
|
-
|
3322
|
-
|
4652
|
+
with suppress(Exception):
|
4653
|
+
make_driver_executable_if_not(
|
4654
|
+
LOCAL_CHROMEDRIVER
|
4655
|
+
)
|
4656
|
+
shutil.copy2(LOCAL_CHROMEDRIVER, LOCAL_UC_DRIVER)
|
3323
4657
|
elif os.path.exists(path_chromedriver):
|
3324
|
-
|
3325
|
-
|
3326
|
-
|
4658
|
+
with suppress(Exception):
|
4659
|
+
make_driver_executable_if_not(
|
4660
|
+
path_chromedriver
|
4661
|
+
)
|
4662
|
+
shutil.copy2(path_chromedriver, LOCAL_UC_DRIVER)
|
3327
4663
|
try:
|
3328
4664
|
make_driver_executable_if_not(LOCAL_UC_DRIVER)
|
3329
4665
|
except Exception as e:
|
@@ -3354,6 +4690,12 @@ def get_local_driver(
|
|
3354
4690
|
chrome_options.arguments.remove(
|
3355
4691
|
"--headless"
|
3356
4692
|
)
|
4693
|
+
if "--headless=old" in (
|
4694
|
+
chrome_options.arguments
|
4695
|
+
):
|
4696
|
+
chrome_options.arguments.remove(
|
4697
|
+
"--headless=old"
|
4698
|
+
)
|
3357
4699
|
uc_chrome_version = None
|
3358
4700
|
if (
|
3359
4701
|
use_version.isnumeric()
|
@@ -3388,7 +4730,7 @@ def get_local_driver(
|
|
3388
4730
|
chrome_options.add_argument(
|
3389
4731
|
"--user-agent=%s" % user_agent
|
3390
4732
|
)
|
3391
|
-
|
4733
|
+
with suppress(Exception):
|
3392
4734
|
if (
|
3393
4735
|
(
|
3394
4736
|
not user_agent
|
@@ -3397,6 +4739,7 @@ def get_local_driver(
|
|
3397
4739
|
and uc_chrome_version
|
3398
4740
|
and uc_chrome_version >= 117
|
3399
4741
|
and (headless or headless2)
|
4742
|
+
and chromium_arg != "decoy"
|
3400
4743
|
):
|
3401
4744
|
from seleniumbase.console_scripts import (
|
3402
4745
|
sb_install
|
@@ -3416,6 +4759,7 @@ def get_local_driver(
|
|
3416
4759
|
None, # multi_proxy
|
3417
4760
|
None, # user_agent
|
3418
4761
|
None, # recorder_ext
|
4762
|
+
disable_cookies,
|
3419
4763
|
disable_js,
|
3420
4764
|
disable_csp,
|
3421
4765
|
enable_ws,
|
@@ -3427,6 +4771,7 @@ def get_local_driver(
|
|
3427
4771
|
False, # log_cdp_events
|
3428
4772
|
no_sandbox,
|
3429
4773
|
disable_gpu,
|
4774
|
+
False, # headless1
|
3430
4775
|
False, # headless2
|
3431
4776
|
incognito,
|
3432
4777
|
guest_mode,
|
@@ -3494,7 +4839,7 @@ def get_local_driver(
|
|
3494
4839
|
service=service,
|
3495
4840
|
options=headless_options,
|
3496
4841
|
)
|
3497
|
-
|
4842
|
+
with suppress(Exception):
|
3498
4843
|
user_agent = driver.execute_script(
|
3499
4844
|
"return navigator.userAgent;"
|
3500
4845
|
)
|
@@ -3516,16 +4861,12 @@ def get_local_driver(
|
|
3516
4861
|
"--user-agent=%s" % user_agent
|
3517
4862
|
)
|
3518
4863
|
sb_config.uc_agent_cache = user_agent
|
3519
|
-
except Exception:
|
3520
|
-
pass
|
3521
4864
|
driver.quit()
|
3522
|
-
|
3523
|
-
|
4865
|
+
uc_path = None
|
4866
|
+
if os.path.exists(LOCAL_UC_DRIVER):
|
4867
|
+
uc_path = LOCAL_UC_DRIVER
|
4868
|
+
uc_path = os.path.realpath(uc_path)
|
3524
4869
|
try:
|
3525
|
-
uc_path = None
|
3526
|
-
if os.path.exists(LOCAL_UC_DRIVER):
|
3527
|
-
uc_path = LOCAL_UC_DRIVER
|
3528
|
-
uc_path = os.path.realpath(uc_path)
|
3529
4870
|
driver = undetected.Chrome(
|
3530
4871
|
options=chrome_options,
|
3531
4872
|
user_data_dir=user_data_dir,
|
@@ -3538,10 +4879,28 @@ def get_local_driver(
|
|
3538
4879
|
)
|
3539
4880
|
uc_activated = True
|
3540
4881
|
except URLError as e:
|
3541
|
-
if
|
4882
|
+
if (
|
4883
|
+
IS_MAC
|
4884
|
+
and hasattr(e, "args")
|
4885
|
+
and isinstance(e.args, (list, tuple))
|
4886
|
+
and cert in e.args[0]
|
4887
|
+
):
|
3542
4888
|
mac_certificate_error = True
|
3543
4889
|
else:
|
3544
4890
|
raise
|
4891
|
+
except SessionNotCreatedException:
|
4892
|
+
time.sleep(0.2)
|
4893
|
+
driver = undetected.Chrome(
|
4894
|
+
options=chrome_options,
|
4895
|
+
user_data_dir=user_data_dir,
|
4896
|
+
driver_executable_path=uc_path,
|
4897
|
+
browser_executable_path=b_path,
|
4898
|
+
enable_cdp_events=cdp_events,
|
4899
|
+
headless=False, # Xvfb needed!
|
4900
|
+
version_main=uc_chrome_version,
|
4901
|
+
use_subprocess=True, # Always!
|
4902
|
+
)
|
4903
|
+
uc_activated = True
|
3545
4904
|
if mac_certificate_error:
|
3546
4905
|
cf_lock_path = (
|
3547
4906
|
constants.MultiBrowser.CERT_FIXING_LOCK
|
@@ -3552,6 +4911,10 @@ def get_local_driver(
|
|
3552
4911
|
if not os.path.exists(cf_lock_path):
|
3553
4912
|
# Avoid multithreaded issues
|
3554
4913
|
with cf_lock:
|
4914
|
+
with suppress(Exception):
|
4915
|
+
shared_utils.make_writable(
|
4916
|
+
cf_lock_path
|
4917
|
+
)
|
3555
4918
|
# Install Python Certificates (MAC)
|
3556
4919
|
os.system(
|
3557
4920
|
r"bash /Applications/Python*/"
|
@@ -3648,6 +5011,7 @@ def get_local_driver(
|
|
3648
5011
|
None, # multi_proxy
|
3649
5012
|
None, # user_agent
|
3650
5013
|
None, # recorder_ext
|
5014
|
+
disable_cookies,
|
3651
5015
|
disable_js,
|
3652
5016
|
disable_csp,
|
3653
5017
|
enable_ws,
|
@@ -3659,6 +5023,7 @@ def get_local_driver(
|
|
3659
5023
|
False, # log_cdp_events
|
3660
5024
|
no_sandbox,
|
3661
5025
|
disable_gpu,
|
5026
|
+
False, # headless1
|
3662
5027
|
False, # headless2
|
3663
5028
|
incognito,
|
3664
5029
|
guest_mode,
|
@@ -3693,6 +5058,10 @@ def get_local_driver(
|
|
3693
5058
|
constants.MultiBrowser.DRIVER_FIXING_LOCK
|
3694
5059
|
)
|
3695
5060
|
with chromedriver_fixing_lock:
|
5061
|
+
with suppress(Exception):
|
5062
|
+
shared_utils.make_writable(
|
5063
|
+
constants.MultiBrowser.DRIVER_FIXING_LOCK
|
5064
|
+
)
|
3696
5065
|
if not _was_driver_repaired():
|
3697
5066
|
_repair_chromedriver(
|
3698
5067
|
chrome_options, headless_options, mcv
|
@@ -3724,6 +5093,9 @@ def get_local_driver(
|
|
3724
5093
|
options=chrome_options,
|
3725
5094
|
)
|
3726
5095
|
driver.default_get = driver.get # Save copy of original
|
5096
|
+
driver.cdp = None # Set a placeholder
|
5097
|
+
driver._is_using_cdp = False
|
5098
|
+
driver._is_connected = True
|
3727
5099
|
if uc_activated:
|
3728
5100
|
driver.get = lambda url: uc_special_open_if_cf(
|
3729
5101
|
driver,
|
@@ -3743,20 +5115,87 @@ def get_local_driver(
|
|
3743
5115
|
driver, *args, **kwargs
|
3744
5116
|
)
|
3745
5117
|
)
|
5118
|
+
driver.uc_open_with_disconnect = (
|
5119
|
+
lambda *args, **kwargs: uc_open_with_disconnect(
|
5120
|
+
driver, *args, **kwargs
|
5121
|
+
)
|
5122
|
+
)
|
3746
5123
|
driver.uc_click = lambda *args, **kwargs: uc_click(
|
3747
5124
|
driver, *args, **kwargs
|
3748
5125
|
)
|
5126
|
+
driver.uc_activate_cdp_mode = (
|
5127
|
+
lambda *args, **kwargs: uc_activate_cdp_mode(
|
5128
|
+
driver, *args, **kwargs
|
5129
|
+
)
|
5130
|
+
)
|
5131
|
+
driver.uc_open_with_cdp_mode = (
|
5132
|
+
lambda *args, **kwargs: uc_open_with_cdp_mode(
|
5133
|
+
driver, *args, **kwargs
|
5134
|
+
)
|
5135
|
+
)
|
5136
|
+
driver.uc_gui_press_key = (
|
5137
|
+
lambda *args, **kwargs: uc_gui_press_key(
|
5138
|
+
driver, *args, **kwargs
|
5139
|
+
)
|
5140
|
+
)
|
5141
|
+
driver.uc_gui_press_keys = (
|
5142
|
+
lambda *args, **kwargs: uc_gui_press_keys(
|
5143
|
+
driver, *args, **kwargs
|
5144
|
+
)
|
5145
|
+
)
|
5146
|
+
driver.uc_gui_write = (
|
5147
|
+
lambda *args, **kwargs: uc_gui_write(
|
5148
|
+
driver, *args, **kwargs
|
5149
|
+
)
|
5150
|
+
)
|
5151
|
+
driver.uc_gui_click_x_y = (
|
5152
|
+
lambda *args, **kwargs: uc_gui_click_x_y(
|
5153
|
+
driver, *args, **kwargs
|
5154
|
+
)
|
5155
|
+
)
|
5156
|
+
driver.uc_gui_click_captcha = (
|
5157
|
+
lambda *args, **kwargs: uc_gui_click_captcha(
|
5158
|
+
driver, *args, **kwargs
|
5159
|
+
)
|
5160
|
+
)
|
5161
|
+
driver.uc_gui_click_cf = (
|
5162
|
+
lambda *args, **kwargs: uc_gui_click_cf(
|
5163
|
+
driver, *args, **kwargs
|
5164
|
+
)
|
5165
|
+
)
|
5166
|
+
driver.uc_gui_click_rc = (
|
5167
|
+
lambda *args, **kwargs: uc_gui_click_rc(
|
5168
|
+
driver, *args, **kwargs
|
5169
|
+
)
|
5170
|
+
)
|
5171
|
+
driver.uc_gui_handle_captcha = (
|
5172
|
+
lambda *args, **kwargs: uc_gui_handle_captcha(
|
5173
|
+
driver, *args, **kwargs
|
5174
|
+
)
|
5175
|
+
)
|
5176
|
+
driver.uc_gui_handle_cf = (
|
5177
|
+
lambda *args, **kwargs: uc_gui_handle_cf(
|
5178
|
+
driver, *args, **kwargs
|
5179
|
+
)
|
5180
|
+
)
|
5181
|
+
driver.uc_gui_handle_rc = (
|
5182
|
+
lambda *args, **kwargs: uc_gui_handle_rc(
|
5183
|
+
driver, *args, **kwargs
|
5184
|
+
)
|
5185
|
+
)
|
3749
5186
|
driver.uc_switch_to_frame = (
|
3750
5187
|
lambda *args, **kwargs: uc_switch_to_frame(
|
3751
5188
|
driver, *args, **kwargs
|
3752
5189
|
)
|
3753
5190
|
)
|
5191
|
+
driver._is_hidden = (headless or headless2)
|
5192
|
+
driver._is_using_uc = True
|
3754
5193
|
if mobile_emulator:
|
3755
5194
|
uc_metrics = {}
|
3756
5195
|
if (
|
3757
5196
|
isinstance(device_width, int)
|
3758
5197
|
and isinstance(device_height, int)
|
3759
|
-
and isinstance(device_pixel_ratio, int)
|
5198
|
+
and isinstance(device_pixel_ratio, (int, float))
|
3760
5199
|
):
|
3761
5200
|
uc_metrics["width"] = device_width
|
3762
5201
|
uc_metrics["height"] = device_height
|
@@ -3773,13 +5212,11 @@ def get_local_driver(
|
|
3773
5212
|
"mobile": True
|
3774
5213
|
}
|
3775
5214
|
)
|
3776
|
-
|
5215
|
+
with suppress(Exception):
|
3777
5216
|
driver.execute_cdp_cmd(
|
3778
5217
|
'Emulation.setDeviceMetricsOverride',
|
3779
5218
|
set_device_metrics_override
|
3780
5219
|
)
|
3781
|
-
except Exception:
|
3782
|
-
pass
|
3783
5220
|
return extend_driver(driver)
|
3784
5221
|
else: # Running headless on Linux (and not using --uc)
|
3785
5222
|
try:
|
@@ -3823,25 +5260,24 @@ def get_local_driver(
|
|
3823
5260
|
chromedr_fixing_lock = fasteners.InterProcessLock(
|
3824
5261
|
constants.MultiBrowser.DRIVER_FIXING_LOCK
|
3825
5262
|
)
|
5263
|
+
D_F_L = constants.MultiBrowser.DRIVER_FIXING_LOCK
|
3826
5264
|
with chromedr_fixing_lock:
|
5265
|
+
with suppress(Exception):
|
5266
|
+
shared_utils.make_writable(D_F_L)
|
3827
5267
|
if not _was_driver_repaired():
|
3828
|
-
|
5268
|
+
with suppress(Exception):
|
3829
5269
|
_repair_chromedriver(
|
3830
5270
|
chrome_options, chrome_options, mcv
|
3831
5271
|
)
|
3832
5272
|
_mark_driver_repaired()
|
3833
|
-
except Exception:
|
3834
|
-
pass
|
3835
5273
|
else:
|
3836
5274
|
if not _was_driver_repaired():
|
3837
|
-
|
5275
|
+
with suppress(Exception):
|
3838
5276
|
_repair_chromedriver(
|
3839
5277
|
chrome_options, chrome_options, mcv
|
3840
5278
|
)
|
3841
|
-
except Exception:
|
3842
|
-
pass
|
3843
5279
|
_mark_driver_repaired()
|
3844
|
-
|
5280
|
+
with suppress(Exception):
|
3845
5281
|
service = ChromeService(
|
3846
5282
|
log_output=os.devnull,
|
3847
5283
|
service_args=["--disable-build-check"],
|
@@ -3851,8 +5287,6 @@ def get_local_driver(
|
|
3851
5287
|
options=chrome_options,
|
3852
5288
|
)
|
3853
5289
|
return extend_driver(driver)
|
3854
|
-
except Exception:
|
3855
|
-
pass
|
3856
5290
|
# Use the virtual display on Linux during headless errors
|
3857
5291
|
logging.debug(
|
3858
5292
|
"\nWarning: Chrome failed to launch in"
|
@@ -3861,6 +5295,8 @@ def get_local_driver(
|
|
3861
5295
|
)
|
3862
5296
|
if "--headless" in chrome_options.arguments:
|
3863
5297
|
chrome_options.arguments.remove("--headless")
|
5298
|
+
if "--headless=old" in chrome_options.arguments:
|
5299
|
+
chrome_options.arguments.remove("--headless=old")
|
3864
5300
|
service = ChromeService(
|
3865
5301
|
log_output=os.devnull,
|
3866
5302
|
service_args=["--disable-build-check"]
|
@@ -3869,18 +5305,16 @@ def get_local_driver(
|
|
3869
5305
|
service=service, options=chrome_options
|
3870
5306
|
)
|
3871
5307
|
return extend_driver(driver)
|
3872
|
-
except Exception:
|
5308
|
+
except Exception as original_exception:
|
3873
5309
|
if is_using_uc(undetectable, browser_name):
|
3874
5310
|
raise
|
3875
5311
|
# Try again if Chrome didn't launch
|
3876
|
-
|
5312
|
+
with suppress(Exception):
|
3877
5313
|
service = ChromeService(service_args=["--disable-build-check"])
|
3878
5314
|
driver = webdriver.Chrome(
|
3879
5315
|
service=service, options=chrome_options
|
3880
5316
|
)
|
3881
5317
|
return extend_driver(driver)
|
3882
|
-
except Exception:
|
3883
|
-
pass
|
3884
5318
|
if user_data_dir:
|
3885
5319
|
print("\nUnable to set user_data_dir while starting Chrome!\n")
|
3886
5320
|
raise
|
@@ -3905,8 +5339,11 @@ def get_local_driver(
|
|
3905
5339
|
log_output=os.devnull,
|
3906
5340
|
service_args=["--disable-build-check"]
|
3907
5341
|
)
|
3908
|
-
|
3909
|
-
|
5342
|
+
try:
|
5343
|
+
driver = webdriver.Chrome(service=service)
|
5344
|
+
return extend_driver(driver)
|
5345
|
+
except Exception:
|
5346
|
+
raise original_exception
|
3910
5347
|
else:
|
3911
5348
|
raise Exception(
|
3912
5349
|
"%s is not a valid browser option for this system!" % browser_name
|