Skip to content

Commit 6be3260

Browse files
committed
Update CDP Mode
1 parent 25f68b3 commit 6be3260

5 files changed

Lines changed: 87 additions & 26 deletions

File tree

examples/cdp_mode/ReadMe.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ sb.cdp.select_all(selector, timeout=None)
391391
sb.cdp.find_elements(selector, timeout=None)
392392
sb.cdp.find_visible_elements(selector, timeout=None)
393393
sb.cdp.click(selector, timeout=None)
394-
sb.cdp.click_if_visible(selector)
394+
sb.cdp.click_if_visible(selector, timeout=0)
395395
sb.cdp.click_visible_elements(selector, limit=0)
396396
sb.cdp.click_nth_element(selector, number)
397397
sb.cdp.click_nth_visible_element(selector, number)

seleniumbase/core/browser_launcher.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,12 +1338,12 @@ def _uc_gui_click_captcha(
13381338
_on_a_captcha_page = None
13391339
if ctype == "cf_t":
13401340
if not _on_a_cf_turnstile_page(driver):
1341-
return
1341+
return False
13421342
else:
13431343
_on_a_captcha_page = _on_a_cf_turnstile_page
13441344
elif ctype == "g_rc":
13451345
if not _on_a_g_recaptcha_page(driver):
1346-
return
1346+
return False
13471347
else:
13481348
_on_a_captcha_page = _on_a_g_recaptcha_page
13491349
else:
@@ -1354,7 +1354,7 @@ def _uc_gui_click_captcha(
13541354
ctype = "cf_t"
13551355
_on_a_captcha_page = _on_a_cf_turnstile_page
13561356
else:
1357-
return
1357+
return False
13581358
install_pyautogui_if_missing(driver)
13591359
import pyautogui
13601360
pyautogui = get_configured_pyautogui(pyautogui)
@@ -1505,7 +1505,7 @@ def _uc_gui_click_captcha(
15051505
):
15061506
frame = "div:not([class]) > div:not([class])"
15071507
else:
1508-
return
1508+
return False
15091509
if (
15101510
driver.is_element_present("form")
15111511
and (
@@ -1605,9 +1605,9 @@ def _uc_gui_click_captcha(
16051605
if driver.is_connected():
16061606
driver.switch_to_frame("iframe")
16071607
else:
1608-
return
1608+
return False
16091609
if not i_x or not i_y:
1610-
return
1610+
return False
16111611
try:
16121612
if ctype == "g_rc" and not driver.is_connected():
16131613
x = (i_x + 29) * width_ratio
@@ -1638,7 +1638,7 @@ def _uc_gui_click_captcha(
16381638
try:
16391639
driver.switch_to.default_content()
16401640
except Exception:
1641-
return
1641+
return False
16421642
if x and y:
16431643
sb_config._saved_cf_x_y = (x, y)
16441644
if not __is_cdp_swap_needed(driver):
@@ -1652,7 +1652,7 @@ def _uc_gui_click_captcha(
16521652
_uc_gui_click_x_y(driver, x, y, timeframe=0.32)
16531653
if __is_cdp_swap_needed(driver):
16541654
time.sleep(float(constants.UC.RECONNECT_TIME) / 2.0)
1655-
return
1655+
return True
16561656
reconnect_time = (float(constants.UC.RECONNECT_TIME) / 2.0) + 0.6
16571657
if IS_LINUX:
16581658
reconnect_time = constants.UC.RECONNECT_TIME + 0.2
@@ -1684,17 +1684,17 @@ def _uc_gui_click_captcha(
16841684
try:
16851685
driver.switch_to_frame("iframe")
16861686
except Exception:
1687-
return
1687+
return False
16881688
checkbox_success = None
16891689
if ctype == "cf_t":
16901690
checkbox_success = "#success-icon"
16911691
elif ctype == "g_rc":
16921692
checkbox_success = "span.recaptcha-checkbox-checked"
16931693
else:
1694-
return # If this line is reached, ctype wasn't set
1694+
return False # If line is reached, ctype wasn't set
16951695
if driver.is_element_visible("#success-icon"):
16961696
driver.switch_to.parent_frame(checkbox_success)
1697-
return
1697+
return True
16981698
if blind:
16991699
driver.uc_open_with_disconnect(driver.get_current_url(), 3.8)
17001700
if __is_cdp_swap_needed(driver) and _on_a_captcha_page(driver):
@@ -1708,6 +1708,7 @@ def _uc_gui_click_captcha(
17081708
_uc_gui_click_x_y(driver, x, y, timeframe=0.32)
17091709
if not cdp_mode_on_at_start:
17101710
driver.reconnect(reconnect_time)
1711+
return True
17111712

17121713

17131714
def uc_gui_click_captcha(driver, frame="iframe", retry=False, blind=False):

seleniumbase/core/sb_cdp.py

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -791,10 +791,10 @@ def click_active_element(self):
791791
self.__slow_mode_pause_if_set()
792792
self.loop.run_until_complete(self.page.wait())
793793

794-
def click_if_visible(self, selector):
794+
def click_if_visible(self, selector, timeout=0):
795795
if self.is_element_visible(selector):
796796
with suppress(Exception):
797-
element = self.find_element(selector, timeout=0)
797+
element = self.find_element(selector, timeout=timeout)
798798
element.scroll_into_view()
799799
element.click()
800800
self.__slow_mode_pause_if_set()
@@ -1969,6 +1969,12 @@ def _on_a_cf_turnstile_page(self, source=None):
19691969
return True
19701970
return False
19711971

1972+
def _on_an_incapsula_hcaptcha_page(self, *args, **kwargs):
1973+
self.loop.run_until_complete(self.page.wait())
1974+
if self.is_element_visible('iframe[src*="_Incapsula_Resource?"]'):
1975+
return True
1976+
return False
1977+
19721978
def _on_a_g_recaptcha_page(self, *args, **kwargs):
19731979
time.sleep(0.4) # reCAPTCHA may need a moment to appear
19741980
self.loop.run_until_complete(self.page.wait())
@@ -1999,20 +2005,34 @@ def __gui_click_recaptcha(self, use_cdp=False):
19992005
if self.is_element_visible('iframe[title="reCAPTCHA"]'):
20002006
selector = 'iframe[title="reCAPTCHA"]'
20012007
else:
2002-
return
2008+
return False
20032009
time.sleep(0.25)
20042010
self.loop.run_until_complete(self.page.wait())
20052011
time.sleep(0.25)
20062012
with suppress(Exception):
2007-
element_rect = self.get_gui_element_rect(selector, timeout=1)
2013+
element_rect = self.get_element_rect(selector, timeout=0.1)
20082014
e_x = element_rect["x"]
20092015
e_y = element_rect["y"]
2016+
window_rect = self.get_window_rect()
2017+
win_width = window_rect["innerWidth"]
2018+
win_height = window_rect["innerHeight"]
2019+
if (
2020+
e_x > 1040
2021+
and e_y > 640
2022+
and abs(win_width - e_x) < 110
2023+
and abs(win_height - e_y) < 110
2024+
):
2025+
# Probably the invisible reCAPTCHA in the bottom right corner
2026+
return False
2027+
gui_element_rect = self.get_gui_element_rect(selector, timeout=1)
2028+
gui_e_x = gui_element_rect["x"]
2029+
gui_e_y = gui_element_rect["y"]
20102030
x_offset = 26
20112031
y_offset = 35
20122032
if shared_utils.is_windows():
20132033
x_offset = 29
2014-
x = e_x + x_offset
2015-
y = e_y + y_offset
2034+
x = gui_e_x + x_offset
2035+
y = gui_e_y + y_offset
20162036
sb_config._saved_cf_x_y = (x, y)
20172037
time.sleep(0.08)
20182038
if use_cdp:
@@ -2025,6 +2045,33 @@ def __gui_click_recaptcha(self, use_cdp=False):
20252045
time.sleep(0.056)
20262046
else:
20272047
self.gui_click_x_y(x, y)
2048+
return True
2049+
return False
2050+
2051+
def __cdp_click_incapsula_hcaptcha(self):
2052+
selector = None
2053+
if self.is_element_visible('iframe[src*="_Incapsula_Resource?"]'):
2054+
outer_selector = 'iframe[src*="_Incapsula_Resource?"]'
2055+
selector = "iframe[data-hcaptcha-widget-id]"
2056+
element = self.get_nested_element(outer_selector, selector)
2057+
if not element:
2058+
return False
2059+
else:
2060+
return False
2061+
time.sleep(0.05)
2062+
self.loop.run_until_complete(self.page.wait())
2063+
time.sleep(0.05)
2064+
x_offset = 30
2065+
y_offset = 36
2066+
gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
2067+
with gui_lock: # Prevent issues with multiple processes
2068+
self.bring_active_window_to_front()
2069+
time.sleep(0.05)
2070+
with suppress(Exception):
2071+
element.click_with_offset(x_offset, y_offset)
2072+
time.sleep(0.2)
2073+
return True
2074+
return False
20282075

20292076
def solve_captcha(self):
20302077
self.__click_captcha(use_cdp=True)
@@ -2046,10 +2093,13 @@ def __click_captcha(self, use_cdp=False):
20462093
if self._on_a_cf_turnstile_page(source):
20472094
pass
20482095
elif self._on_a_g_recaptcha_page(source):
2049-
self.__gui_click_recaptcha(use_cdp)
2050-
return
2096+
result = self.__gui_click_recaptcha(use_cdp)
2097+
return result
2098+
elif self._on_an_incapsula_hcaptcha_page():
2099+
result = self.__cdp_click_incapsula_hcaptcha()
2100+
return result
20512101
else:
2052-
return
2102+
return False
20532103
selector = None
20542104
if self.is_element_present('[class="cf-turnstile"]'):
20552105
selector = '[class="cf-turnstile"]'
@@ -2085,6 +2135,10 @@ def __click_captcha(self, use_cdp=False):
20852135
'[class*="turnstile"] div:not([class])'
20862136
):
20872137
selector = '[class*="turnstile"] div:not([class])'
2138+
elif self.is_element_present(
2139+
"iframe[data-hcaptcha-widget-id]"
2140+
):
2141+
selector = "iframe[data-hcaptcha-widget-id]"
20882142
elif self.is_element_present(
20892143
'[data-callback="onCaptchaSuccess"]'
20902144
):
@@ -2094,9 +2148,9 @@ def __click_captcha(self, use_cdp=False):
20942148
):
20952149
selector = "div:not([class]) > div:not([class])"
20962150
else:
2097-
return
2151+
return False
20982152
if not selector:
2099-
return
2153+
return False
21002154
if (
21012155
self.is_element_present("form")
21022156
and (
@@ -2204,6 +2258,8 @@ def __click_captcha(self, use_cdp=False):
22042258
time.sleep(0.05)
22052259
else:
22062260
self.gui_click_x_y(x, y)
2261+
return True
2262+
return False
22072263

22082264
def __gui_drag_drop(self, x1, y1, x2, y2, timeframe=0.25, uc_lock=False):
22092265
self.__install_pyautogui_if_missing()

seleniumbase/fixtures/base_case.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2415,7 +2415,7 @@ def click_if_visible(self, selector, by="css selector", timeout=0):
24152415
If a "timeout" is provided, waits that long for the element
24162416
to appear before giving up and returning without a click()."""
24172417
if self.__is_cdp_swap_needed():
2418-
self.cdp.click_if_visible(selector)
2418+
self.cdp.click_if_visible(selector, timeout=timeout)
24192419
return
24202420
self.wait_for_ready_state_complete()
24212421
if self.is_element_visible(selector, by=by):

seleniumbase/fixtures/js_utils.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,7 +1374,10 @@ def slow_scroll_to_element(driver, element, *args, **kwargs):
13741374
element_location_x_fix = 0
13751375
if element_location_x + element_width <= screen_width:
13761376
element_location_x_fix = 0
1377-
distance = element_location_y - scroll_position
1377+
if shared_utils.is_cdp_swap_needed(driver):
1378+
distance = element_location_y
1379+
else:
1380+
distance = element_location_y - scroll_position
13781381
if distance != 0:
13791382
total_steps = int(abs(distance) / 50.0) + 2.0
13801383
step_value = float(distance) / total_steps
@@ -1388,7 +1391,8 @@ def slow_scroll_to_element(driver, element, *args, **kwargs):
13881391
scroll_script = "window.scrollTo(%s, %s);" % (
13891392
element_location_x_fix, element_location_y
13901393
)
1391-
execute_script(driver, scroll_script)
1394+
if not shared_utils.is_cdp_swap_needed(driver):
1395+
execute_script(driver, scroll_script)
13921396
time.sleep(0.01)
13931397
if distance > 430 or distance < -300:
13941398
# Add small recovery time for long-distance slow-scrolling

0 commit comments

Comments
 (0)