Skip to content

Commit

Permalink
Merge pull request #3232 from seleniumbase/cdp-mode-patch-4
Browse files Browse the repository at this point in the history
CDP Mode - Patch 4
  • Loading branch information
mdmintz authored Oct 28, 2024
2 parents dbe6fbb + 6c2d6e3 commit 533619d
Show file tree
Hide file tree
Showing 17 changed files with 114 additions and 65 deletions.
88 changes: 45 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@

👤 Note that <span translate="no">SeleniumBase</span> <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/uc_mode.md"><b>UC Mode</b> (Stealth Mode) has its own ReadMe</a>.

🐙 Also note that Seleniumbase <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md"><b>CDP Mode</b> has its own separate ReadMe</a>.

ℹ️ Scripts can be called via <code translate="no"><b>python</b></code>, although some <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/syntax_formats.md">Syntax Formats</a> expect <a href="https://docs.pytest.org/en/latest/how-to/usage.html" translate="no"><b>pytest</b></a> (a Python unit-testing framework included with SeleniumBase that can discover, collect, and run tests automatically).

<p align="left">📗 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/my_first_test.py">my_first_test.py</a>, which tests login, shopping, and checkout:</p>
Expand Down Expand Up @@ -315,48 +317,49 @@ pip install -e .
🔵 **Type ``seleniumbase`` or ``sbase`` to verify that SeleniumBase was installed successfully:**

```bash
______ __ _ ____
/ ____/__ / /__ ____ (_)_ ______ ___ / _ \____ ________
\__ \/ _ \/ / _ \/ __ \/ / / / / __ `__ \ / /_) / __ \/ ___/ _ \
___/ / __/ / __/ / / / / /_/ / / / / / // /_) / (_/ /__ / __/
/____/\___/_/\___/_/ /_/_/\__,_/_/ /_/ /_//_____/\__,_/____/\___/
------------------------------------------------------------------
* USAGE: "seleniumbase [COMMAND] [PARAMETERS]"
* OR: "sbase [COMMAND] [PARAMETERS]"
COMMANDS:
get / install [DRIVER] [OPTIONS]
methods (List common Python methods)
options (List common pytest options)
behave-options (List common behave options)
gui / commander [OPTIONAL PATH or TEST FILE]
behave-gui (SBase Commander for Behave)
caseplans [OPTIONAL PATH or TEST FILE]
mkdir [DIRECTORY] [OPTIONS]
mkfile [FILE.py] [OPTIONS]
mkrec / codegen [FILE.py] [OPTIONS]
recorder (Open Recorder Desktop App.)
record (If args: mkrec. Else: App.)
mkpres [FILE.py] [LANG]
mkchart [FILE.py] [LANG]
print [FILE] [OPTIONS]
translate [SB_FILE.py] [LANG] [ACTION]
convert [WEBDRIVER_UNITTEST_FILE.py]
extract-objects [SB_FILE.py]
inject-objects [SB_FILE.py] [OPTIONS]
objectify [SB_FILE.py] [OPTIONS]
revert-objects [SB_FILE.py] [OPTIONS]
encrypt / obfuscate
decrypt / unobfuscate
download server (Get Selenium Grid JAR file)
grid-hub [start|stop] [OPTIONS]
grid-node [start|stop] --hub=[HOST/IP]
* (EXAMPLE: "sbase get chromedriver latest") *
Type "sbase help [COMMAND]" for specific command info.
For info on all commands, type: "seleniumbase --help".
Use "pytest" for running tests.
___ _ _ ___
/ __| ___| |___ _ _ (_)_ _ _ __ | _ ) __ _ ______
\__ \/ -_) / -_) ' \| | \| | ' \ | _ \/ _` (_-< -_)
|___/\___|_\___|_||_|_|\_,_|_|_|_\|___/\__,_/__|___|
----------------------------------------------------
╭──────────────────────────────────────────────────╮
* USAGE: "seleniumbase [COMMAND] [PARAMETERS]"
* OR: "sbase [COMMAND] [PARAMETERS]"
│ │
│ COMMANDS: PARAMETERS / DESCRIPTIONS: │
│ get / install [DRIVER_NAME] [OPTIONS] │
│ methods (List common Python methods) │
│ options (List common pytest options) │
│ behave-options (List common behave options) │
│ gui / commander [OPTIONAL PATH or TEST FILE] │
│ behave-gui (SBase Commander for Behave) │
│ caseplans [OPTIONAL PATH or TEST FILE] │
│ mkdir [DIRECTORY] [OPTIONS] │
│ mkfile [FILE.py] [OPTIONS] │
│ mkrec / codegen [FILE.py] [OPTIONS] │
│ recorder (Open Recorder Desktop App.) │
│ record (If args: mkrec. Else: App.) │
│ mkpres [FILE.py] [LANG] │
│ mkchart [FILE.py] [LANG] │
│ print [FILE] [OPTIONS] │
│ translate [SB_FILE.py] [LANG] [ACTION] │
│ convert [WEBDRIVER_UNITTEST_FILE.py] │
│ extract-objects [SB_FILE.py] │
│ inject-objects [SB_FILE.py] [OPTIONS] │
│ objectify [SB_FILE.py] [OPTIONS] │
│ revert-objects [SB_FILE.py] [OPTIONS] │
│ encrypt / obfuscate │
│ decrypt / unobfuscate │
│ proxy (Start a basic proxy server) │
│ download server (Get Selenium Grid JAR file) │
│ grid-hub [start|stop] [OPTIONS] │
│ grid-node [start|stop] --hub=[HOST/IP] │
│ │
* EXAMPLE => "sbase get chromedriver stable"
* For command info => "sbase help [COMMAND]"
* For info on all commands => "sbase --help"
╰──────────────────────────────────────────────────╯
```

<h3>🔵 Downloading webdrivers:</h3>
Expand Down Expand Up @@ -1375,7 +1378,6 @@ pytest --reruns=1 --reruns-delay=1
<span><a href="https://github.com/seleniumbase/SeleniumBase"><img src="https://seleniumbase.github.io/img/social/share_github.svg" title="SeleniumBase on GitHub" alt="SeleniumBase on GitHub" width="64" /></a></span>
<span><a href="https://discord.gg/EdhQTn3EyE"><img src="https://seleniumbase.github.io/other/discord_icon.png" title="SeleniumBase on Discord" alt="SeleniumBase on Discord" width="66" /></a></span>
<span><a href="https://www.facebook.com/SeleniumBase"><img src="https://seleniumbase.io/img/social/share_facebook.svg" title="SeleniumBase on Facebook" alt="SeleniumBase on Facebook" width="62" /></a></span>
<span><a href="https://gitter.im/seleniumbase/SeleniumBase" target="_blank"><img src="https://seleniumbase.github.io/img/social/share_gitter.svg" title="SeleniumBase on Gitter" alt="SeleniumBase on Gitter" width="48" /></a></span>
</div></p>
<p><div><b><a href="https://github.com/mdmintz">https://github.com/mdmintz</a></b></div></p>
Expand Down
16 changes: 16 additions & 0 deletions examples/cdp_mode/raw_antibot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from seleniumbase import SB

with SB(uc=True, test=True) as sb:
url = "https://seleniumbase.io/antibot/login"
sb.activate_cdp_mode(url)
sb.press_keys("input#username", "demo_user")
sb.press_keys("input#password", "secret_pass")
x, y = sb.cdp.get_gui_element_center("button#myButton")
sb.uc_gui_click_x_y(x, y)
sb.sleep(1.5)
x, y = sb.cdp.get_gui_element_center("a#log-in")
sb.uc_gui_click_x_y(x, y)
sb.assert_text("Welcome!", "h1")
sb.set_messenger_theme(location="bottom_center")
sb.post_message("SeleniumBase wasn't detected!")
sb.sleep(1.5)
11 changes: 11 additions & 0 deletions examples/cdp_mode/raw_gitlab.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from seleniumbase import SB

with SB(uc=True, test=True, locale_code="en") as sb:
url = "https://gitlab.com/users/sign_in"
sb.activate_cdp_mode(url)
sb.uc_gui_click_captcha()
sb.assert_text("Username", '[for="user_login"]', timeout=3)
sb.assert_element('label[for="user_login"]')
sb.highlight('button:contains("Sign in")')
sb.highlight('h1:contains("GitLab.com")')
sb.post_message("SeleniumBase wasn't detected", duration=4)
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ colorama>=0.4.6
pyyaml>=6.0.2
pygments>=2.18.0
pyreadline3>=3.5.3;platform_system=="Windows"
tabcompleter>=1.3.3
pdbp>=1.5.4
tabcompleter>=1.4.0
pdbp>=1.6.0
idna==3.10
chardet==5.2.0
charset-normalizer==3.4.0
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.32.3"
__version__ = "4.32.4"
1 change: 1 addition & 0 deletions seleniumbase/core/browser_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,7 @@ def uc_open_with_cdp_mode(driver, url=None):
driver.cdp_base = loop.run_until_complete(
cdp_util.start(host=cdp_host, port=cdp_port)
)

page = loop.run_until_complete(driver.cdp_base.get(url))
loop.run_until_complete(page.activate())
if not safe_url:
Expand Down
4 changes: 2 additions & 2 deletions seleniumbase/fixtures/base_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -4167,13 +4167,13 @@ def get_new_driver(
device_pixel_ratio=d_p_r,
browser=browser_name,
)
time.sleep(0.2)
time.sleep(0.16)
except Exception:
pass
finally:
with suppress(Exception):
decoy_driver.quit()
time.sleep(0.1)
time.sleep(0.08)
# Launch a web browser
new_driver = browser_launcher.get_driver(
browser_name=browser_name,
Expand Down
4 changes: 2 additions & 2 deletions seleniumbase/plugins/driver_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -870,13 +870,13 @@ def Driver(
device_pixel_ratio=d_p_r,
browser=browser_name,
)
time.sleep(0.2)
time.sleep(0.16)
except Exception:
pass
finally:
with suppress(Exception):
decoy_driver.quit()
time.sleep(0.1)
time.sleep(0.08)

driver = browser_launcher.get_driver(
browser_name=browser_name,
Expand Down
19 changes: 13 additions & 6 deletions seleniumbase/undetected/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
import logging
import os
import re
Expand Down Expand Up @@ -433,10 +432,15 @@ def reconnect(self, timeout=0.1):
time.sleep(timeout)
with suppress(Exception):
self.service.start()
time.sleep(0.012)
with suppress(Exception):
self.start_session()
time.sleep(0.012)
with suppress(Exception):
if self.current_url.startswith("chrome-extension://"):
self.close()
self.service.stop()
self.service.start()
self.start_session()
self._is_connected = True

def disconnect(self):
"""Stops the chromedriver service that runs in the background.
Expand All @@ -445,19 +449,22 @@ def disconnect(self):
with suppress(Exception):
self.service.stop()
self._is_connected = False
time.sleep(0.012)

def connect(self):
"""Starts the chromedriver service that runs in the background
and recreates the session."""
if hasattr(self, "service"):
with suppress(Exception):
self.service.start()
time.sleep(0.012)
with suppress(Exception):
self.start_session()
with suppress(Exception):
if self.current_url.startswith("chrome-extension://"):
self.close()
self.service.stop()
self.service.start()
self.start_session()
self._is_connected = True
time.sleep(0.012)

def start_session(self, capabilities=None):
if not capabilities:
Expand Down
1 change: 0 additions & 1 deletion seleniumbase/undetected/cdp.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
import fasteners
import json
import logging
Expand Down
7 changes: 7 additions & 0 deletions seleniumbase/undetected/cdp_driver/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import sys
import tempfile
import zipfile
from seleniumbase.config import settings
from typing import Union, List, Optional

__all__ = [
Expand Down Expand Up @@ -101,7 +102,13 @@ def __init__(
# Other keyword args will be accessible by attribute
self.__dict__.update(kwargs)
super().__init__()
start_width = settings.CHROME_START_WIDTH
start_height = settings.CHROME_START_HEIGHT
start_x = settings.WINDOW_START_X
start_y = settings.WINDOW_START_Y
self._default_browser_args = [
"--window-size=%s,%s" % (start_width, start_height),
"--window-position=%s,%s" % (start_x, start_y),
"--remote-allow-origins=*",
"--no-first-run",
"--no-service-autorun",
Expand Down
10 changes: 9 additions & 1 deletion seleniumbase/undetected/cdp_driver/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,14 @@ async def aclose(self):
if self.listener and self.listener.running:
self.listener.cancel()
self.enabled_domains.clear()
await self.websocket.close()
await asyncio.sleep(0.015)
try:
await self.websocket.close()
except Exception:
logger.debug(
"\n❌ Error closing websocket connection to %s",
self.websocket_url
)
logger.debug(
"\n❌ Closed websocket connection to %s", self.websocket_url
)
Expand Down Expand Up @@ -540,6 +547,7 @@ async def listener_loop(self):
self.idle.set()
# Pause for a moment.
# await asyncio.sleep(self.time_before_considered_idle / 10)
await asyncio.sleep(0.015)
continue
except (Exception,) as e:
logger.debug(
Expand Down
1 change: 0 additions & 1 deletion seleniumbase/undetected/dprocess.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
import os
import sys
import atexit
Expand Down
5 changes: 3 additions & 2 deletions seleniumbase/undetected/options.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
import json
import os
from contextlib import suppress
Expand Down Expand Up @@ -59,7 +58,9 @@ def handle_prefs(self, user_data_dir):
json.load(f), undot_prefs
)
with suppress(Exception):
with open(prefs_file, encoding="utf-8", mode="w") as f:
with open(
prefs_file, encoding="utf-8", mode="w", errors="ignore"
) as f:
json.dump(undot_prefs, f)
# Remove experimental_options to avoid errors
del self._experimental_options["prefs"]
Expand Down
1 change: 0 additions & 1 deletion seleniumbase/undetected/patcher.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
import io
import logging
import os
Expand Down
1 change: 0 additions & 1 deletion seleniumbase/undetected/reactor.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
import asyncio
import json
import logging
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,8 @@
'pyyaml>=6.0.2',
'pygments>=2.18.0',
'pyreadline3>=3.5.3;platform_system=="Windows"',
"tabcompleter>=1.3.3",
"pdbp>=1.5.4",
"tabcompleter>=1.4.0",
"pdbp>=1.6.0",
"idna==3.10",
'chardet==5.2.0',
'charset-normalizer==3.4.0',
Expand Down

0 comments on commit 533619d

Please sign in to comment.