Skip to content
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
8 changes: 7 additions & 1 deletion examples/cdp_mode/ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,12 @@ sb.save_as_html(name, folder=None)
sb.save_screenshot(name, folder=None, selector=None)
sb.print_to_pdf(name, folder=None)
sb.save_as_pdf(name, folder=None)
sb.save_as_pdf_to_logs(name=None)
sb.save_screenshot_to_logs(name=None, selector=None)
sb.save_page_source_to_logs(name=None)
sb.save_as_html_to_logs(name=None)
sb.save_data_to_logs(data, file_name=None)
sb.append_data_to_logs(data, file_name=None)
sb.quit() # (Pure CDP Mode only: `sb_cdp`)
```

Expand Down Expand Up @@ -667,7 +673,7 @@ await page.click_if_visible(selector, timeout=0)
await page.click_with_offset(selector, x, y, center=False, timeout=5)
await page.solve_captcha()
await page.click_captcha() # Same as solve_captcha()
await page.reload(ignore_cache=True, script_to_evaluate_on_load=None)
await page.reload(ignore_cache=False, script_to_evaluate_on_load=None)
await page.evaluate(expression)
await page.js_dumps(obj_name)
await page.back()
Expand Down
4 changes: 3 additions & 1 deletion examples/cdp_mode/playwright/raw_etsy_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
sb.goto("https://www.etsy.com/")
sb.sleep(1)
search = "FIFA Keychains"
required_text = "keychain"
required_text = "Keychain"
sb.type('input[data-id="search-query"]', search)
sb.sleep(1)
sb.click('button[aria-label="Search"]')
Expand All @@ -18,6 +18,8 @@
page = browser.contexts[0].pages[0]
items = page.locator("div.v2-listing-card__info")
num = 0
print('*** Etsy search for "%s":' % search)
print(' (Results must contain "%s")' % required_text)
for i in range(items.count()):
title = items.nth(i).locator("h3.v2-listing-card__title").inner_text()
price = items.nth(i).locator("div.n-listing-card__price").inner_text()
Expand Down
4 changes: 1 addition & 3 deletions examples/cdp_mode/playwright/raw_nordstrom_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
search_box = page.locator("input#keyword-search-input")
search_box.press_sequentially(search + "\n", delay=80)
page.wait_for_timeout(2200)
for i in range(17):
sb.scroll_down(16)
sb.sleep(0.14)
print('*** Nordstrom Search for "%s":' % search)
unique_item_text = []
items = sb.find_elements("article")
Expand All @@ -30,3 +27,4 @@
if price:
price_text = price.text
print("* %s (%s)" % (description.text, price_text))
item.flash(color="44CC88")
12 changes: 10 additions & 2 deletions examples/cdp_mode/raw_ad_blocking.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ async def block_urls(tab):
"*.doubleclick.net*",
"*.fastclick.net*",
"*.snigelweb.com*",
"*.viously.com*",
"*.flashb.id*",
"*.2mdn.net*",
]
))
Expand All @@ -27,7 +29,13 @@ async def block_urls(tab):
loop.run_until_complete(block_urls(sb.get_active_tab()))
sb.goto("https://www.w3schools.com/jquery/default.asp")
source = sb.get_page_source()
sb.assert_false("doubleclick.net" in source)
sb.assert_false("google-analytics.com" in source)
try:
sb.assert_false("doubleclick.net" in source)
sb.assert_false("google-analytics.com" in source)
except Exception:
sb.refresh()
source = sb.get_page_source()
sb.assert_false("doubleclick.net" in source)
sb.assert_false("google-analytics.com" in source)
sb.post_message("Blocking was successful!")
sb.quit()
5 changes: 5 additions & 0 deletions examples/cdp_mode/raw_basic_cdp.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
links = top_nav.query_selector_all("a")
for nav_item in links:
print(nav_item.text)
sb.save_as_pdf_to_logs()
sb.save_screenshot_to_logs()
sb.save_page_source_to_logs()
sb.save_data_to_logs("hello!")
sb.append_data_to_logs("more data!")
sb.click_link("Sign out")
sb.assert_text("signed out", "#top_message")
sb.quit()
4 changes: 3 additions & 1 deletion examples/cdp_mode/raw_cdp_etsy.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
sb.goto("https://www.etsy.com/")
sb.sleep(1)
search = "FIFA Keychains"
required_text = "keychain"
required_text = "Keychain"
sb.type('input[data-id="search-query"]', search)
sb.sleep(1)
sb.click('button[aria-label="Search"]')
Expand All @@ -13,6 +13,8 @@
soup = sb.get_beautiful_soup()
items = soup.select("div.v2-listing-card__info")
num = 0
print('*** Etsy search for "%s":' % search)
print(' (Results must contain "%s")' % required_text)
for item in items:
title_element = item.select_one("h3.v2-listing-card__title")
price_element = item.select_one("div.n-listing-card__price")
Expand Down
2 changes: 1 addition & 1 deletion examples/cdp_mode/raw_cdp_fingerprint.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from seleniumbase import sb_cdp

sb = sb_cdp.Chrome()
sb = sb_cdp.Chrome(use_chromium=True)
sb.goto("https://demo.fingerprint.com/playground")
sb.wait_for_element('a[href*="browser-bot-detection"]')
sb.flash('a[href*="browser-bot-detection"]', duration=3, pause=1)
Expand Down
2 changes: 1 addition & 1 deletion examples/cdp_mode/raw_cdp_nordstrom.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
if price:
price_text = price.text
print("* %s (%s)" % (description.text, price_text))
sb.scroll_down(16)
item.flash(color="44CC88")
sb.quit()
28 changes: 17 additions & 11 deletions examples/cdp_mode/raw_homedepot.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,26 @@
sb.click("button#typeahead-search-icon-button")
sb.sleep(3.8)
sb.click('a[aria-label="%s"]' % category)
sb.sleep(3.2)
sb.sleep(3.8)
print('*** Home Depot Search for "%s":' % search)
print(' (Results must contain "%s".)' % required_text)
unique_item_text = []
items = sb.find_elements('div[data-testid="product-pod"]')
product_pod = 'div[data-testid="product-pod"]'
sb.wait_for_element(product_pod)
soup = sb.get_beautiful_soup()
items = soup.select(product_pod)
for item in items:
if required_text in item.text:
description = item.querySelector(
item_text = item.get_text()
if required_text in item_text:
description = item.select_one(
'span[data-testid="attribute-product-label"]'
)
if description and description.text not in unique_item_text:
unique_item_text.append(description.text)
print("* " + description.text)
price = item.querySelector('[class*="sm:sui-text-4xl"]')
if price:
price_text = "$%s" % price.text
print(" (" + price_text + ")")
if description:
description_text = description.get_text(strip=True)
if description_text not in unique_item_text:
unique_item_text.append(description_text)
print("* " + description_text)
price = item.select_one('[class*="sm:sui-text-4xl"]')
if price:
price_text = "$%s" % price.get_text(strip=True)
print(" (" + price_text + ")")
2 changes: 1 addition & 1 deletion examples/cdp_mode/raw_indeed_jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
sb.click('button[type="submit"]')
sb.sleep(3.6)
items = sb.find_visible_elements('[data-testid*="jobcard"]')
print('*** %s:' % search)
print('*** Indeed search for "%s":' % search)
for i, item in enumerate(items):
print(f"* <====== {i + 1} ======>")
print(item.text)
Expand Down
25 changes: 15 additions & 10 deletions examples/cdp_mode/raw_mouser.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
from seleniumbase import SB

with SB(uc=True, test=True, locale="en") as sb:
with SB(uc=True, test=True, guest=True) as sb:
sb.activate_cdp_mode()
sb.goto("https://www.mouser.com/")
sb.sleep(5)
sb.press_keys('input[name="keyword"]', "FLUKE-TC01B 25HZ")
search_box = 'input[name="keyword"]'
sb.sleep(1.6)
sb.solve_captcha()
sb.sleep(1.8)
sb.wait_for_element(search_box)
sb.sleep(1.2)
sb.press_keys(search_box, "FLUKE-TC01B 25HZ")
sb.sleep(1.2)
sb.click('button[type="submit"]')
sb.sleep(2)
sb.highlight("h1")
sb.highlight("span#spnDescription")
sb.highlight("td.ext-price-col")
print(sb.get_text("h1"))
print(sb.get_text("span#spnDescription"))
print(sb.get_text("td.ext-price-col"))
sb.sleep(3.2)
sb.wait_for_element("span#spnDescription")
soup = sb.get_beautiful_soup()
print(soup.select_one("h1").get_text(strip=True))
print(soup.select_one("span#spnDescription").get_text(strip=True))
print(soup.select_one("td.ext-price-col").get_text(strip=True))
4 changes: 2 additions & 2 deletions examples/cdp_mode/raw_muse.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
with SB(uc=True, test=True, guest=True) as sb:
sb.activate_cdp_mode()
sb.goto("https://muse.jhu.edu/verify")
sb.sleep(1.6)
sb.sleep(0.6)
sb.solve_captcha()
sb.sleep(4)
sb.assert_element('#search_input')
sb.sleep(3)
sb.sleep(2.5)
4 changes: 2 additions & 2 deletions examples/cdp_mode/raw_muse_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ async def main():
url = "https://muse.jhu.edu/verify"
driver = await cdp_driver.start_async(guest=True)
page = await driver.get(url)
await page.sleep(2.5)
await page.sleep(1.2)
await page.solve_captcha()
await page.sleep(4)
await page.find('#search_input')
await page.sleep(3)
await page.sleep(2.5)

if __name__ == "__main__":
asyncio.run(main())
2 changes: 1 addition & 1 deletion examples/cdp_mode/raw_nordstrom.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@
if price:
price_text = price.text
print("* %s (%s)" % (description.text, price_text))
sb.scroll_down(16)
item.flash(color="44CC88")
25 changes: 15 additions & 10 deletions examples/cdp_mode/raw_zoro.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,20 @@
sb.sleep(3.2)
sb.wait_for_element('[data-za="product-cards-list"]', timeout=5)
print('*** Zoro Search for "%s":' % search)
print(' (Results must contain "%s".)' % required_text)
print(' (Results must contain "%s")' % required_text)
unique_item_text = []
items = sb.find_elements('[data-za="search-product-card"]')
soup = sb.get_beautiful_soup()
items = soup.select('[data-za="search-product-card"]')
for item in items:
if required_text in item.text:
description = item.querySelector("h2")
if description and description.text not in unique_item_text:
unique_item_text.append(description.text)
print("* " + description.text)
price = item.querySelector("div.price-main")
if price:
print(" (" + price.text + ")")
item_text = item.get_text()
if required_text.lower() in item_text.lower():
description_element = item.select_one("h2")
if description_element:
description_text = description_element.get_text(strip=True)
if description_text.lower() not in unique_item_text:
unique_item_text.append(description_text.lower())
print("* " + description_text)
price_element = item.select_one("div.price-main")
if price_element:
price_text = " ".join(price_element.get_text().split())
print(" (" + price_text + ")")
12 changes: 10 additions & 2 deletions examples/test_cdp_ad_blocking.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,18 @@ def test_cdp_network_blocking(self):
"*.doubleclick.net*",
"*.fastclick.net*",
"*.snigelweb.com*",
"*.viously.com*",
"*.flashb.id*",
"*.2mdn.net*",
]})
self.goto("https://www.w3schools.com/jquery/default.asp")
source = self.get_page_source()
self.assert_false("doubleclick.net" in source)
self.assert_false("google-analytics.com" in source)
try:
self.assert_false("doubleclick.net" in source)
self.assert_false("google-analytics.com" in source)
except Exception:
self.refresh()
source = self.get_page_source()
self.assert_false("doubleclick.net" in source)
self.assert_false("google-analytics.com" in source)
self.post_message("Blocking was successful!")
8 changes: 7 additions & 1 deletion help_docs/cdp_mode_methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Here's a list of SeleniumBase CDP Mode method definitions, which are defined in
sb.get(url, **kwargs)
sb.open(url, **kwargs) # Same as sb.get(url, **kwargs) in CDP Mode
sb.goto(url, **kwargs) # Same as sb.get(url, **kwargs) in CDP Mode
sb.reload(ignore_cache=True, script_to_evaluate_on_load=None)
sb.reload(ignore_cache=False, script_to_evaluate_on_load=None)
sb.refresh(*args, **kwargs)
sb.goto_if_not_url(url)
sb.get_event_loop()
Expand Down Expand Up @@ -209,6 +209,12 @@ sb.save_as_html(name, folder=None)
sb.save_screenshot(name, folder=None, selector=None)
sb.print_to_pdf(name, folder=None)
sb.save_as_pdf(name, folder=None)
sb.save_as_pdf_to_logs(name=None)
sb.save_screenshot_to_logs(name=None, selector=None)
sb.save_page_source_to_logs(name=None)
sb.save_as_html_to_logs(name=None)
sb.save_data_to_logs(data, file_name=None)
sb.append_data_to_logs(data, file_name=None)
sb.quit() # (Pure CDP Mode only: `sb_cdp`)
```

Expand Down
1 change: 1 addition & 0 deletions help_docs/method_summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ self.save_as_pdf_to_logs(name=None)
self.save_data_to_logs(data, file_name=None)
self.append_data_to_logs(data, file_name=None)
self.save_page_source_to_logs(name=None)
# Duplicates: self.save_as_html_to_logs(name, folder=None)
self.save_page_source(name, folder=None)
# Duplicates: self.save_as_html(name, folder=None)
self.save_cookies(name="cookies.txt")
Expand Down
4 changes: 2 additions & 2 deletions mkdocs_build/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# mkdocs dependencies for generating the seleniumbase.io website
# Minimum Python version: 3.10 (for generating docs only)

regex>=2026.6.28
regex>=2026.7.10
pymdown-extensions>=10.21.3
pipdeptree>=3.1.1
python-dateutil>=2.8.2
Expand All @@ -17,5 +17,5 @@ mkdocs==1.6.1
mkdocs-material==9.6.23
mkdocs-exclude-search==0.6.6
mkdocs-simple-hooks==0.1.5
mkdocs-get-deps==0.2.0
mkdocs-get-deps==0.2.2
mkdocs-material-extensions==1.3.1
8 changes: 4 additions & 4 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ attrs>=26.1.0
certifi>=2026.6.17
exceptiongroup>=1.3.1
websockets~=15.0.1;python_version<"3.10"
websockets>=16.0;python_version>="3.10"
websockets>=16.1;python_version>="3.10"
filelock~=3.19.1;python_version<"3.10"
filelock>=3.29.6;python_version>="3.10"
filelock>=3.29.7;python_version>="3.10"
fasteners>=0.20
mycdp>=1.4.0
pynose>=1.5.5
Expand Down Expand Up @@ -46,7 +46,7 @@ wsproto==1.2.0;python_version<"3.10"
wsproto~=1.3.2;python_version>="3.10"
websocket-client~=1.9.0
selenium==4.32.0;python_version<"3.10"
selenium==4.45.0;python_version>="3.10"
selenium==4.46.0;python_version>="3.10"
cssselect==1.3.0;python_version<"3.10"
cssselect>=1.4.0,<2;python_version>="3.10"
sortedcontainers==2.4.0
Expand Down Expand Up @@ -80,7 +80,7 @@ rich>=15.0.0,<16
# ("pip install -r requirements.txt" also installs this, but "pip install -e ." won't.)

coverage>=7.10.7;python_version<"3.10"
coverage>=7.15.0;python_version>="3.10"
coverage>=7.15.1;python_version>="3.10"
pytest-cov>=7.1.0
flake8==7.3.0
mccabe==0.7.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.50.6"
__version__ = "4.51.0"
7 changes: 7 additions & 0 deletions seleniumbase/core/browser_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,12 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
cdp.save_screenshot = CDPM.save_screenshot
cdp.print_to_pdf = CDPM.print_to_pdf
cdp.save_as_pdf = CDPM.save_as_pdf
cdp.save_as_pdf_to_logs = CDPM.save_as_pdf_to_logs
cdp.save_screenshot_to_logs = CDPM.save_screenshot_to_logs
cdp.save_page_source_to_logs = CDPM.save_page_source_to_logs
cdp.save_as_html_to_logs = CDPM.save_as_html_to_logs
cdp.save_data_to_logs = CDPM.save_data_to_logs
cdp.append_data_to_logs = CDPM.append_data_to_logs
cdp.page = page # async world
cdp.driver = driver.cdp_base # async world
cdp.tab = cdp.page # shortcut (original)
Expand Down Expand Up @@ -3093,6 +3099,7 @@ def get_driver(
browser=None, # A duplicate of browser_name to avoid confusion
):
sb_config._ext_dirs = []
sb_config._cdp_launched = False
driver_dir = DRIVER_DIR
if binary_location == "_chromium_":
driver_dir = DRIVER_DIR_CHROMIUM
Expand Down
Loading