From 111f8eefbd3c6597ef1f37775e6f3ad81a604b91 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Wed, 4 Sep 2024 22:48:41 -0400 Subject: [PATCH 1/5] Improve UC Mode methods --- seleniumbase/core/browser_launcher.py | 90 +++++++++++---------------- 1 file changed, 36 insertions(+), 54 deletions(-) diff --git a/seleniumbase/core/browser_launcher.py b/seleniumbase/core/browser_launcher.py index 9e41ed3d9cd..413aec8d36c 100644 --- a/seleniumbase/core/browser_launcher.py +++ b/seleniumbase/core/browser_launcher.py @@ -861,10 +861,19 @@ def _uc_gui_click_captcha( visible_iframe = False if ( frame != "iframe" - and driver.is_element_present('[name*="cf-turnstile-"]') - and driver.is_element_present("%s div[style]" % frame) + and driver.is_element_present( + "%s .cf-turnstile-wrapper" % frame + ) + ): + frame = "%s .cf-turnstile-wrapper" % frame + elif ( + frame != "iframe" + and driver.is_element_present( + '%s [name*="cf-turnstile"]' % frame + ) + and driver.is_element_present("%s div" % frame) ): - frame = "%s div[style]" % frame + frame = "%s div" % frame elif ( driver.is_element_present('[name*="cf-turnstile-"]') and driver.is_element_present("div.spacer div") @@ -877,47 +886,21 @@ def _uc_gui_click_captcha( ) ): frame = '[data-testid*="challenge-"] div' - elif ( - ( - driver.is_element_present('[name*="cf-turnstile-"]') - or driver.is_element_present('[id*="cf-turnstile-"]') - ) - and driver.is_element_present( - 'form div div[style*="margin"][style*="padding"]' - ) - ): - frame = 'form div div[style*="margin"][style*="padding"]' - elif ( - frame != "iframe" - and driver.is_element_present( - "%s .cf-turnstile-wrapper" % frame - ) + elif driver.is_element_present( + 'form div:not([class]):has(input[name*="cf-turn"])' ): - frame = "%s .cf-turnstile-wrapper" % frame + frame = 'form div:not([class]):has(input[name*="cf-turn"])' elif ( - frame != "iframe" - and driver.is_element_present( - '%s [name*="cf-turnstile"]' % frame - ) - and driver.is_element_present("%s div" % frame) + driver.is_element_present('[src*="/turnstile/"]') + and driver.is_element_present("form div:not(:has(*))") ): - frame = "%s div" % frame + frame = "form div:not(:has(*))" elif driver.is_element_present(".cf-turnstile-wrapper"): frame = ".cf-turnstile-wrapper" elif driver.is_element_present( '[data-callback="onCaptchaSuccess"]' ): frame = '[data-callback="onCaptchaSuccess"]' - elif ( - ( - driver.is_element_present('[name*="cf-turnstile-"]') - or driver.is_element_present('[id*="cf-turnstile-"]') - ) - and driver.is_element_present( - 'div > div > [style*="margin"][style*="padding"]' - ) - ): - frame = 'div > div > [style*="margin"][style*="padding"]' else: return if driver.is_element_present('form[class*=center]'): @@ -1100,6 +1083,8 @@ def _uc_gui_handle_captcha( driver.minimize_window() driver.set_window_rect(win_x, win_y, width, height) time.sleep(0.33) + tab_up_first = False + special_form = False if ctype == "cf_t": if ( driver.is_element_present(".cf-turnstile-wrapper iframe") @@ -1128,26 +1113,18 @@ def _uc_gui_handle_captcha( ) ): frame = '[data-testid*="challenge-"] div' - elif ( - ( - driver.is_element_present('[name*="cf-turnstile-"]') - or driver.is_element_present('[id*="cf-turnstile-"]') - ) - and driver.is_element_present( - 'form div div[style*="margin"][style*="padding"]' - ) + elif driver.is_element_present( + 'form div:not([class]):has(input[name*="cf-turn"])' ): - frame = 'form div div[style*="margin"][style*="padding"]' + frame = 'form div:not([class]):has(input[name*="cf-turn"])' + tab_up_first = True + special_form = True elif ( - ( - driver.is_element_present('[name*="cf-turnstile-"]') - or driver.is_element_present('[id*="cf-turnstile-"]') - ) - and driver.is_element_present( - 'div > div > [style*="margin"][style*="padding"]' - ) + driver.is_element_present('[src*="/turnstile/"]') + and driver.is_element_present("form div:not(:has(*))") ): - frame = 'div > div > [style*="margin"][style*="padding"]' + frame = "form div:not(:has(*))" + tab_up_first = True else: return else: @@ -1172,13 +1149,18 @@ def _uc_gui_handle_captcha( if ctype == "g_rc": selector = "span#recaptcha-anchor" found_checkbox = False - for i in range(24): + if tab_up_first: + for i in range(10): + pyautogui.hotkey("shift", "tab") + time.sleep(0.027) + for i in range(34): pyautogui.press("\t") - time.sleep(0.02) + time.sleep(0.027) active_element_css = js_utils.get_active_element_css(driver) if ( active_element_css.startswith(selector) or active_element_css.endswith(" > div" * 2) + or (special_form and active_element_css.endswith(" div")) ): found_checkbox = True break From fab150b88193abc73389f8bc40441a2084b00bb0 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Wed, 4 Sep 2024 22:59:03 -0400 Subject: [PATCH 2/5] Update examples --- examples/presenter/uc_presentation.py | 21 +++++++++-------- examples/presenter/uc_presentation_3.py | 30 ++++++++++++------------- examples/raw_ahrefs.py | 4 ++-- examples/raw_cf.py | 8 +++---- examples/raw_order_tickets.py | 3 ++- examples/raw_pixelscan.py | 12 +++++----- 6 files changed, 40 insertions(+), 38 deletions(-) diff --git a/examples/presenter/uc_presentation.py b/examples/presenter/uc_presentation.py index ba6247cdc0c..ae5ff4dc2f2 100644 --- a/examples/presenter/uc_presentation.py +++ b/examples/presenter/uc_presentation.py @@ -30,12 +30,12 @@ def test_presentation(self): self.get_new_driver(undetectable=True) url = "https://gitlab.com/users/sign_in" try: - self.driver.uc_open_with_reconnect(url, reconnect_time=3) + self.uc_open_with_reconnect(url, reconnect_time=3) try: self.assert_text("Username", '[for="user_login"]', timeout=3) self.post_message("SeleniumBase wasn't detected", duration=4) except Exception: - self.driver.uc_open_with_reconnect(url, reconnect_time=4) + self.uc_open_with_reconnect(url, reconnect_time=4) self.assert_text("Username", '[for="user_login"]', timeout=3) self.post_message("SeleniumBase wasn't detected", duration=4) finally: @@ -249,8 +249,7 @@ def test_presentation(self): code=( "from seleniumbase import SB\n\n" "with SB(uc=True) as sb:\n" - ' sb.driver.get(' - '"https://seleniumbase.io/simple/login")\n' + ' sb.get("seleniumbase.io/simple/login")\n' ' sb.type("#username", "demo_user")\n' ' sb.type("#password", "secret_pass")\n' ' sb.click(\'a:contains("Sign in")\')\n' @@ -266,7 +265,7 @@ def test_presentation(self): try: with SB(uc=True) as sb: - sb.driver.get("https://seleniumbase.io/simple/login") + sb.get("https://seleniumbase.io/simple/login") sb.type("#username", "demo_user") sb.type("#password", "secret_pass") sb.click('a:contains("Sign in")') @@ -285,7 +284,7 @@ def test_presentation(self): code=( "from seleniumbase import SB\n\n" "with SB(uc=True, demo=True) as sb:\n" - ' sb.driver.get(' + ' sb.get(' '"https://seleniumbase.io/simple/login")\n' ' sb.type("#username", "demo_user")\n' ' sb.type("#password", "secret_pass")\n' @@ -301,7 +300,7 @@ def test_presentation(self): try: with SB(uc=True, demo=True) as sb: - sb.driver.get("https://seleniumbase.io/simple/login") + sb.get("https://seleniumbase.io/simple/login") sb.type("#username", "demo_user") sb.type("#password", "secret_pass") sb.click('a:contains("Sign in")') @@ -340,11 +339,11 @@ def test_presentation(self): code=( "from seleniumbase import SB\n\n" "with SB(uc=True) as sb:\n" - ' sb.driver.get("https://nowsecure.nl/#relax")\n' + ' sb.get("https://nowsecure.nl/#relax")\n' " sb.sleep(1)\n" ' if not sb.is_text_visible("OH YEAH, you passed", "h1"):\n' " sb.get_new_driver(undetectable=True)\n" - ' sb.driver.get("https://nowsecure.nl/#relax")\n' + ' sb.get("https://nowsecure.nl/#relax")\n' " sb.sleep(1)\n" ' sb.activate_demo_mode()\n' ' sb.assert_text("OH YEAH, you passed!", "h1", timeout=3)\n' @@ -354,10 +353,10 @@ def test_presentation(self): try: with SB(uc=True) as sb: - sb.driver.uc_open_with_tab("https://nowsecure.nl/#relax") + sb.uc_open_with_tab("https://nowsecure.nl/#relax") sb.sleep(1) if not sb.is_text_visible("OH YEAH, you passed", "h1"): - sb.driver.uc_open_with_tab("https://nowsecure.nl/#relax") + sb.uc_open_with_tab("https://nowsecure.nl/#relax") sb.sleep(1) sb.activate_demo_mode() sb.assert_text("OH YEAH, you passed!", "h1", timeout=3) diff --git a/examples/presenter/uc_presentation_3.py b/examples/presenter/uc_presentation_3.py index bc428759344..a3da212dcd4 100644 --- a/examples/presenter/uc_presentation_3.py +++ b/examples/presenter/uc_presentation_3.py @@ -18,7 +18,7 @@ def test_presentation_3(self): self.begin_presentation(filename="uc_presentation.html") self.open("https://seleniumbase.io/other/uc3_title.jpg") - self.sleep(3) + self.sleep(2.5) self.create_presentation(theme="serif", transition="fade") self.add_slide( @@ -108,11 +108,11 @@ def test_presentation_3(self): "

Special UC Mode methods for clicking CAPTCHAs:" "


" "\n\n\n\n" @@ -171,7 +171,7 @@ def test_presentation_3(self): "with SB(uc=True) as sb:\n" ' url = "https://gitlab.com/users/sign_in"\n' " sb.uc_open_with_reconnect(url, 4)\n" - " uc_gui_handle_captcha()\n\n" + " sb.uc_gui_handle_captcha()\n\n" " ...\n\n\n\n\n\n" ), ) @@ -183,7 +183,7 @@ def test_presentation_3(self): "with SB(uc=True) as sb:\n" ' url = "https://gitlab.com/users/sign_in"\n' " sb.uc_open_with_reconnect(url, 4)\n" - " uc_gui_handle_captcha()\n\n" + " sb.uc_gui_handle_captcha()\n\n" ' sb.assert_text("Username", \'[for="user_login"]\',' ' timeout=3)\n' ' sb.assert_element(\'[for="user_login"]\')\n' @@ -221,7 +221,7 @@ def test_presentation_3(self): "with SB(uc=True) as sb:\n" ' url = "https://gitlab.com/users/sign_in"\n' " sb.uc_open_with_reconnect(url, 4)\n" - " uc_gui_click_captcha()\n\n" + " sb.uc_gui_click_captcha()\n\n" " ...\n\n\n\n\n" ), ) @@ -233,7 +233,7 @@ def test_presentation_3(self): "with SB(uc=True) as sb:\n" ' url = "https://gitlab.com/users/sign_in"\n' " sb.uc_open_with_reconnect(url, 4)\n" - " uc_gui_click_captcha()\n\n" + " sb.uc_gui_click_captcha()\n\n" ' sb.assert_text("Username", \'[for="user_login"]\',' ' timeout=3)\n' ' sb.assert_element(\'[for="user_login"]\')\n' @@ -252,8 +252,8 @@ def test_presentation_3(self): "
  • Navigate with stealth by calling " "sb.uc_open_with_reconnect(url)" "

  • \n" - "
  • Use uc_gui_handle_captcha()" - " or uc_gui_click_captcha()" + "
  • Use sb.uc_gui_handle_captcha()" + " or sb.uc_gui_click_captcha()" " to bypass CAPTCHAs as needed.
  • \n" "\n" "


    (It's that easy!)


    \n" @@ -263,7 +263,7 @@ def test_presentation_3(self): "

    " "