Skip to content

Add UC Mode clicking methods that use PyAutoGUI #2911

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions examples/raw_gui_click.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""
UC Mode now has uc_gui_click_cf(), which uses PyAutoGUI.
An incomplete UserAgent is used to force CAPTCHA-solving.
"""
import sys
from seleniumbase import SB

agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/126.0.0.0"
if "linux" in sys.platform:
agent = None # Use the default UserAgent

with SB(uc=True, test=True, rtf=True, agent=agent) as sb:
url = "https://www.virtualmanager.com/en/login"
sb.uc_open_with_reconnect(url, 4)
sb.uc_gui_click_cf() # Ready if needed!
sb.assert_element('input[name*="email"]')
sb.assert_element('input[name*="login"]')
sb.set_messenger_theme(location="bottom_center")
sb.post_message("SeleniumBase wasn't detected!")
11 changes: 7 additions & 4 deletions examples/raw_order_tickets.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
from seleniumbase import SB

with SB(uc=True, test=True, ad_block_on=True) as sb:
with SB(uc=True, test=True, ad_block=True) as sb:
url = "https://www.thaiticketmajor.com/concert/"
sb.driver.uc_open_with_reconnect(url, 6.111)
sb.driver.uc_click("button.btn-signin", 4.1)
sb.uc_open_with_reconnect(url, 6.111)
sb.uc_click("button.btn-signin", 4.1)
sb.switch_to_frame('iframe[title*="Cloudflare"]')
sb.assert_element("div#success svg#success-icon")
if not sb.is_element_visible("svg#success-icon"):
sb.uc_gui_handle_cf()
sb.switch_to_frame('iframe[title*="Cloudflare"]')
sb.assert_element("svg#success-icon")
sb.switch_to_default_content()
sb.set_messenger_theme(location="top_center")
sb.post_message("SeleniumBase wasn't detected!")
5 changes: 2 additions & 3 deletions examples/raw_uc_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@

with SB(uc=True, test=True) as sb:
url = "https://gitlab.com/users/sign_in"
sb.driver.uc_open_with_reconnect(url, 3)
if not sb.is_text_visible("Username", '[for="user_login"]'):
sb.driver.uc_open_with_reconnect(url, 4)
sb.uc_open_with_reconnect(url, 4)
sb.uc_gui_click_cf()
sb.assert_text("Username", '[for="user_login"]', timeout=3)
sb.assert_element('label[for="user_login"]')
sb.highlight('button:contains("Sign in")')
Expand Down
16 changes: 16 additions & 0 deletions help_docs/method_summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,22 @@ self.execute_async_script(script, timeout=None)

self.safe_execute_script(script, *args, **kwargs)

self.get_gui_element_rect(selector, by="css selector")

self.get_gui_element_center(selector, by="css selector")

self.get_window_rect()

self.get_window_size()

self.get_window_position()

self.set_window_rect(x, y, width, height)

self.set_window_size(width, height)

self.set_window_position(x, y)

self.maximize_window()

self.switch_to_frame(frame="iframe", timeout=None)
Expand Down Expand Up @@ -1062,6 +1074,10 @@ driver.uc_gui_press_keys(keys) # Use PyAutoGUI to press a list of keys

driver.uc_gui_write(text) # Similar to uc_gui_press_keys(), but faster

driver.uc_gui_click_x_y(x, y, timeframe=0.25) # PyAutoGUI click screen

driver.uc_gui_click_cf(frame="iframe", retry=False, blind=False) # (*)

driver.uc_gui_handle_cf(frame="iframe") # PyAutoGUI click CF Turnstile

driver.uc_switch_to_frame(frame="iframe") # Stealthy switch_to_frame()
Expand Down
34 changes: 21 additions & 13 deletions help_docs/uc_mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ from seleniumbase import SB

with SB(uc=True) as sb:
url = "https://gitlab.com/users/sign_in"
sb.driver.uc_open_with_reconnect(url, 3)
sb.uc_open_with_reconnect(url, 3)
```

👤 Here's a longer example, which includes a retry if the CAPTCHA isn't bypassed on the first attempt:
Expand All @@ -52,9 +52,9 @@ from seleniumbase import SB

with SB(uc=True, test=True) as sb:
url = "https://gitlab.com/users/sign_in"
sb.driver.uc_open_with_reconnect(url, 3)
sb.uc_open_with_reconnect(url, 3)
if not sb.is_text_visible("Username", '[for="user_login"]'):
sb.driver.uc_open_with_reconnect(url, 4)
sb.uc_open_with_reconnect(url, 4)
sb.assert_text("Username", '[for="user_login"]', timeout=3)
sb.highlight('label[for="user_login"]', loops=3)
sb.post_message("SeleniumBase wasn't detected", duration=4)
Expand All @@ -78,6 +78,8 @@ with SB(uc=True, test=True) as sb:

<img src="https://seleniumbase.github.io/other/turnstile_click.jpg" title="SeleniumBase" width="440">

If running on a Linux server, `uc_gui_handle_cf()` might not be good enough. Switch to `uc_gui_click_cf()` to be more stealthy.

👤 Here's an example <b>where the CAPTCHA appears after submitting a form</b>:

```python
Expand All @@ -87,10 +89,10 @@ with SB(uc=True, test=True, locale_code="en") as sb:
url = "https://ahrefs.com/website-authority-checker"
input_field = 'input[placeholder="Enter domain"]'
submit_button = 'span:contains("Check Authority")'
sb.driver.uc_open_with_reconnect(url, 1) # The bot-check is later
sb.uc_open_with_reconnect(url, 1) # The bot-check is later
sb.type(input_field, "github.com/seleniumbase/SeleniumBase")
sb.driver.reconnect(0.1)
sb.driver.uc_click(submit_button, reconnect_time=4)
sb.reconnect(0.1)
sb.uc_click(submit_button, reconnect_time=4)
sb.wait_for_text_not_visible("Checking", timeout=10)
sb.highlight('p:contains("github.com/seleniumbase/SeleniumBase")')
sb.highlight('a:contains("Top 100 backlinks")')
Expand All @@ -105,10 +107,10 @@ with SB(uc=True, test=True, locale_code="en") as sb:
```python
from seleniumbase import SB

with SB(uc=True, test=True, ad_block_on=True) as sb:
with SB(uc=True, test=True, ad_block=True) as sb:
url = "https://www.thaiticketmajor.com/concert/"
sb.driver.uc_open_with_reconnect(url, 5.5)
sb.driver.uc_click("button.btn-signin", 4)
sb.uc_open_with_reconnect(url, 5.5)
sb.uc_click("button.btn-signin", 4)
sb.switch_to_frame('iframe[title*="Cloudflare"]')
sb.assert_element("div#success svg#success-icon")
sb.switch_to_default_content()
Expand All @@ -118,7 +120,7 @@ with SB(uc=True, test=True, ad_block_on=True) as sb:

<img src="https://seleniumbase.github.io/other/ttm_bypass.png" title="SeleniumBase" width="540">

👤 <b>On Linux</b>, use `sb.uc_gui_handle_cf()` to handle Cloudflare Turnstiles:
👤 <b>On Linux</b>, use `sb.uc_gui_click_cf()` to handle Cloudflare Turnstiles:

```python
from seleniumbase import SB
Expand All @@ -127,15 +129,15 @@ with SB(uc=True, test=True) as sb:
url = "https://www.virtualmanager.com/en/login"
sb.uc_open_with_reconnect(url, 4)
print(sb.get_page_title())
sb.uc_gui_handle_cf() # Ready if needed!
sb.uc_gui_click_cf() # Ready if needed!
print(sb.get_page_title())
sb.assert_element('input[name*="email"]')
sb.assert_element('input[name*="login"]')
sb.set_messenger_theme(location="bottom_center")
sb.post_message("SeleniumBase wasn't detected!")
```

<a href="https://github.com/mdmintz/undetected-testing/actions/runs/9637461606/job/26576722411"><img width="540" alt="uc_gui_handle_cf on Linux" src="https://github.com/seleniumbase/SeleniumBase/assets/6788579/6aceb2a3-2a32-4521-b30a-f79446d2ce28"></a>
<a href="https://github.com/mdmintz/undetected-testing/actions/runs/9637461606/job/26576722411"><img width="540" alt="uc_gui_click_cf on Linux" src="https://github.com/seleniumbase/SeleniumBase/assets/6788579/6aceb2a3-2a32-4521-b30a-f79446d2ce28"></a>

The 2nd `print()` should output "Virtual Manager", which means that the automation successfully passed the Turnstile.

Expand Down Expand Up @@ -188,6 +190,10 @@ driver.uc_gui_press_keys(keys)

driver.uc_gui_write(text)

driver.uc_gui_click_x_y(x, y, timeframe=0.25)

driver.uc_gui_click_cf(frame="iframe", retry=False, blind=False)

driver.uc_gui_handle_cf(frame="iframe")

driver.uc_switch_to_frame(frame, reconnect_time=None)
Expand Down Expand Up @@ -225,7 +231,9 @@ driver.reconnect("breakpoint")

(Note that while the special <b><code translate="no">UC Mode</code></b> breakpoint is active, you can't use <b><code translate="no">Selenium</code></b> commands in the browser, and the browser can't detect <b><code translate="no">Selenium</code></b>.)

👤 On Linux, you may need to use `driver.uc_gui_handle_cf()` to successfully bypass a Cloudflare CAPTCHA. If there's more than one iframe on that website (and Cloudflare isn't the first one) then put the CSS Selector of that iframe as the first arg to `driver.uc_gui_handle_cf()`. This method uses `pyautogui`. In order for `pyautogui` to focus on the correct element, use `xvfb=True` / `--xvfb` to activate a special virtual display on Linux.
👤 On Linux, you may need to use `driver.uc_gui_click_cf()` to successfully bypass a Cloudflare CAPTCHA. If there's more than one iframe on that website (and Cloudflare isn't the first one) then put the CSS Selector of that iframe as the first arg to `driver.uc_gui_click_cf()`. This method uses `pyautogui`. In order for `pyautogui` to focus on the correct element, use `xvfb=True` / `--xvfb` to activate a special virtual display on Linux.

👤 `driver.uc_gui_click_cf(frame="iframe", retry=False, blind=False)` has three args. (All optional). The first one, `frame`, lets you specify the iframe in case the CAPTCHA is not located in the first iframe on the page. The second one, `retry`, lets you retry the click after reloading the page if the first one didn't work (and a CAPTCHA is still present after the page reload). The third arg, `blind`, will retry after a page reload (if the first click failed) by clicking at the last known coordinates of the CAPTCHA checkbox without confirming first with Selenium that a CAPTCHA is still on the page.

👤 To find out if <b translate="no">UC Mode</b> will work at all on a specific site (before adjusting for timing), load your site with the following script:

Expand Down
2 changes: 1 addition & 1 deletion mkdocs_build/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ lxml==5.2.2
pyquery==2.0.0
readtime==3.0.0
mkdocs==1.6.0
mkdocs-material==9.5.27
mkdocs-material==9.5.28
mkdocs-exclude-search==0.6.6
mkdocs-simple-hooks==0.1.5
mkdocs-material-extensions==1.3.1
6 changes: 3 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ pip>=24.1.1;python_version>="3.8"
packaging>=24.0;python_version<"3.8"
packaging>=24.1;python_version>="3.8"
setuptools>=68.0.0;python_version<"3.8"
setuptools>=70.1.1;python_version>="3.8"
setuptools>=70.2.0;python_version>="3.8"
wheel>=0.42.0;python_version<"3.8"
wheel>=0.43.0;python_version>="3.8"
attrs>=23.2.0
certifi>=2024.6.2
certifi>=2024.7.4
exceptiongroup>=1.2.1
filelock>=3.12.2;python_version<"3.8"
filelock>=3.15.4;python_version>="3.8"
Expand All @@ -29,7 +29,7 @@ sniffio==1.3.1
h11==0.14.0
outcome==1.3.0.post0
trio==0.22.2;python_version<"3.8"
trio==0.25.1;python_version>="3.8"
trio==0.26.0;python_version>="3.8"
trio-websocket==0.11.1
wsproto==1.2.0
websocket-client==1.8.0;python_version>="3.8"
Expand Down
2 changes: 1 addition & 1 deletion seleniumbase/__version__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# seleniumbase package
__version__ = "4.28.3"
__version__ = "4.28.4"
Loading