Skip to content

Commit

Permalink
Merge pull request #3508 from seleniumbase/cdp-mode-patch-32
Browse files Browse the repository at this point in the history
CDP Mode - Patch 32 (and more)
  • Loading branch information
mdmintz authored Feb 12, 2025
2 parents 36b8f78 + 6e83392 commit 291167e
Show file tree
Hide file tree
Showing 16 changed files with 73 additions and 18 deletions.
2 changes: 2 additions & 0 deletions examples/cdp_mode/ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ sb.cdp.flash(selector, duration=1, color="44CC88", pause=0)
sb.cdp.highlight(selector)
sb.cdp.focus(selector)
sb.cdp.highlight_overlay(selector)
sb.cdp.get_parent(element)
sb.cdp.remove_element(selector)
sb.cdp.remove_from_dom(selector)
sb.cdp.remove_elements(selector)
Expand Down Expand Up @@ -522,6 +523,7 @@ element.get_position()
element.get_html()
element.get_js_attributes()
element.get_attribute(attribute)
element.get_parent()
```

--------
Expand Down
2 changes: 1 addition & 1 deletion examples/cdp_mode/raw_cf.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
with SB(uc=True, test=True, locale_code="en") as sb:
url = "https://www.cloudflare.com/login"
sb.activate_cdp_mode(url)
sb.sleep(2)
sb.sleep(3)
sb.uc_gui_handle_captcha() # PyAutoGUI press Tab and Spacebar
sb.sleep(2)

Expand Down
9 changes: 7 additions & 2 deletions examples/cdp_mode/raw_chatgpt.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@
with SB(uc=True, test=True, ad_block=True) as sb:
url = "https://chatgpt.com/"
sb.activate_cdp_mode(url)
sb.sleep(1)
sb.click_if_visible('button[aria-label="Close dialog"]')
query = "Compare Playwright to SeleniumBase in under 178 words"
sb.press_keys("#prompt-textarea", query)
sb.click('button[data-testid="send-button"]')
print('*** Input for ChatGPT: ***\n"%s"' % query)
sb.sleep(3)
with suppress(Exception):
# The "Send" button reappears when ChatGPT is done typing a response
sb.wait_for_element('button[data-testid="send-button"]', timeout=22)
# The "Stop" button disappears when ChatGPT is done typing a response
sb.wait_for_element_not_visible(
'button[data-testid="stop-button"]', timeout=20
)
chat = sb.find_element('[data-message-author-role="assistant"] .markdown')
soup = sb.get_beautiful_soup(chat.get_html()).get_text("\n").strip()
print("*** Response from ChatGPT: ***\n%s" % soup.replace("\n:", ":"))
Expand Down
7 changes: 3 additions & 4 deletions examples/cdp_mode/raw_xhr_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ async def crawl():
# Change url to something that makes ajax requests
tab = await driver.get("https://learn.microsoft.com/en-us/")
time.sleep(2)
for i in range(75):
await tab.scroll_down(3)
for i in range(20):
await tab.scroll_down(4)
time.sleep(0.02)

xhr_responses = await receiveXHR(tab, xhr_requests)
Expand All @@ -87,6 +87,5 @@ async def crawl():

if __name__ == "__main__":
print("<============= START: XHR Example =============>")
loop = asyncio.new_event_loop()
loop.run_until_complete(crawl())
asyncio.run(crawl())
print("<============== END: XHR Example ==============>")
4 changes: 2 additions & 2 deletions examples/cdp_mode/raw_xhr_sb.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ async def receiveXHR(page, requests):
# Change url to something that makes ajax requests
sb.cdp.open("https://learn.microsoft.com/en-us/")
time.sleep(2)
for i in range(15):
sb.cdp.scroll_down(15)
for i in range(10):
sb.cdp.scroll_down(8)

loop = sb.cdp.get_event_loop()
xhr_responses = loop.run_until_complete(receiveXHR(tab, xhr_requests))
Expand Down
7 changes: 4 additions & 3 deletions examples/raw_games.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
"""SB Manager using UC Mode for evading bot-detection."""
from seleniumbase import SB

with SB(uc=True, test=True) as sb:
with SB(uc=True, test=True, disable_csp=True) as sb:
url = "https://steamdb.info/"
sb.uc_open_with_reconnect(url, 3)
sb.uc_click("a.header-login span", 3)
sb.uc_gui_click_captcha()
sb.assert_text("Sign in", "button#js-sign-in")
sb.assert_text("Sign in", "button#js-sign-in", timeout=4)
sb.uc_click("button#js-sign-in", 2)
sb.highlight("div.page_content form")
sb.highlight('button:contains("Sign in")', scroll=False)
sb.sleep(1)
sb.set_messenger_theme(location="top_center")
sb.post_message("SeleniumBase wasn't detected", duration=4)
3 changes: 3 additions & 0 deletions help_docs/method_summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ self.set_attributes(selector, attribute, value, by="css selector")
self.remove_attribute(selector, attribute, by="css selector", timeout=None)
self.remove_attributes(selector, attribute, by="css selector")
self.internalize_links()
self.get_parent(element, by="css selector", timeout=None)
self.get_property(selector, property, by="css selector", timeout=None)
self.get_text_content(selector="html", by="css selector", timeout=None)
self.get_property_value(selector, property, by="css selector", timeout=None)
Expand Down Expand Up @@ -743,6 +744,8 @@ driver.highlight_if_visible(selector)
driver.sleep(seconds)
driver.locator(selector)
driver.get_attribute(selector, attribute)
driver.get_parent(element)
driver.get_current_url()
driver.get_page_source()
driver.get_title()
driver.switch_to_frame(frame="iframe")
Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pip>=25.0
pip>=25.0.1
packaging>=24.2
setuptools~=70.2;python_version<"3.10"
setuptools>=75.8.0;python_version>="3.10"
Expand Down Expand Up @@ -70,7 +70,7 @@ rich==13.9.4
# ("pip install -r requirements.txt" also installs this, but "pip install -e ." won't.)

coverage>=7.6.1;python_version<"3.9"
coverage>=7.6.10;python_version>="3.9"
coverage>=7.6.12;python_version>="3.9"
pytest-cov>=5.0.0;python_version<"3.9"
pytest-cov>=6.0.0;python_version>="3.9"
flake8==5.0.4;python_version<"3.9"
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.34.12"
__version__ = "4.34.13"
15 changes: 15 additions & 0 deletions seleniumbase/core/browser_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ def extend_driver(driver):
driver.highlight_if_visible = DM.highlight_if_visible
driver.sleep = time.sleep
driver.get_attribute = DM.get_attribute
driver.get_parent = DM.get_parent
driver.get_current_url = DM.get_current_url
driver.get_page_source = DM.get_page_source
driver.get_title = DM.get_title
Expand Down Expand Up @@ -647,6 +648,7 @@ def uc_open_with_cdp_mode(driver, url=None):
cdp.click_if_visible = CDPM.click_if_visible
cdp.click_visible_elements = CDPM.click_visible_elements
cdp.mouse_click = CDPM.mouse_click
cdp.get_parent = CDPM.get_parent
cdp.remove_element = CDPM.remove_element
cdp.remove_from_dom = CDPM.remove_from_dom
cdp.remove_elements = CDPM.remove_elements
Expand Down Expand Up @@ -5394,6 +5396,19 @@ def get_local_driver(
)
driver._is_hidden = (headless or headless2)
driver._is_using_uc = True
with suppress(Exception):
if int(uc_driver_version) >= 133:
for window_handle in driver.window_handles:
driver.switch_to.window(window_handle)
if driver.current_url.startswith(
"chrome-extension://"
):
driver.close()
time.sleep(0.003)
driver.switch_to.window(driver.window_handles[0])
time.sleep(0.003)
driver.connect()
time.sleep(0.003)
if mobile_emulator:
uc_metrics = {}
if (
Expand Down
10 changes: 10 additions & 0 deletions seleniumbase/core/sb_cdp.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ def __add_sync_methods(self, element):
element.get_attribute = (
lambda attribute: self.__get_attribute(element, attribute)
)
# element.get_parent() should come last
element.get_parent = lambda: self.__get_parent(element)
return element

def get(self, url):
Expand Down Expand Up @@ -549,6 +551,9 @@ def __get_attribute(self, element, attribute):
pass
return None

def __get_parent(self, element):
return self.__add_sync_methods(element.parent)

def __get_x_scroll_offset(self):
x_scroll_offset = self.loop.run_until_complete(
self.page.evaluate("window.pageXOffset")
Expand Down Expand Up @@ -769,6 +774,11 @@ def focus(self, selector):
def highlight_overlay(self, selector):
self.find_element(selector).highlight_overlay()

def get_parent(self, element):
if isinstance(element, str):
element = self.select(element)
return self.__add_sync_methods(element.parent)

def remove_element(self, selector):
self.select(selector).remove_from_dom()

Expand Down
7 changes: 7 additions & 0 deletions seleniumbase/core/sb_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ def get_attribute(self, selector, attribute, by="css selector"):
element = self.locator(selector, by=by)
return element.get_attribute(attribute)

def get_parent(self, element):
if self.__is_cdp_swap_needed():
return self.driver.cdp.get_parent(element)
if isinstance(element, str):
element = self.locator(element)
return element.find_element(by="xpath", value="..")

def get_current_url(self):
if self.__is_cdp_swap_needed():
current_url = self.driver.cdp.get_current_url()
Expand Down
Binary file modified seleniumbase/extensions/ad_block.zip
Binary file not shown.
Binary file modified seleniumbase/extensions/disable_csp.zip
Binary file not shown.
13 changes: 13 additions & 0 deletions seleniumbase/fixtures/base_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -2072,6 +2072,19 @@ def internalize_links(self):
return
self.set_attributes('[target="_blank"]', "target", "_self")

def get_parent(self, element, by="css selector", timeout=None):
"""Returns the parent element.
If element is a string, then finds element first via selector."""
if self.__is_cdp_swap_needed():
return self.cdp.get_parent(element)
if isinstance(element, str):
if not timeout:
timeout = settings.LARGE_TIMEOUT
element = self.wait_for_element_present(
element, by=by, timeout=timeout
)
return element.find_element(by="xpath", value="..")

def get_property(
self, selector, property, by="css selector", timeout=None
):
Expand Down
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
],
python_requires=">=3.8",
install_requires=[
'pip>=25.0',
'pip>=25.0.1',
'packaging>=24.2',
'setuptools~=70.2;python_version<"3.10"', # Newer ones had issues
'setuptools>=75.8.0;python_version>="3.10"',
Expand Down Expand Up @@ -228,7 +228,7 @@
# Usage: coverage run -m pytest; coverage html; coverage report
"coverage": [
'coverage>=7.6.1;python_version<"3.9"',
'coverage>=7.6.10;python_version>="3.9"',
'coverage>=7.6.12;python_version>="3.9"',
'pytest-cov>=5.0.0;python_version<"3.9"',
'pytest-cov>=6.0.0;python_version>="3.9"',
],
Expand Down Expand Up @@ -259,7 +259,7 @@
"pdfminer": [
'pdfminer.six==20240706',
'cryptography==39.0.2;python_version<"3.9"',
'cryptography==44.0.0;python_version>="3.9"',
'cryptography==44.0.1;python_version>="3.9"',
'cffi==1.17.1',
"pycparser==2.22",
],
Expand Down

0 comments on commit 291167e

Please sign in to comment.