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
31 changes: 31 additions & 0 deletions examples/cdp_mode/playwright/raw_etsy_sync.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from playwright.sync_api import sync_playwright
from seleniumbase import sb_cdp

sb = sb_cdp.Chrome(ad_block=True)
sb.goto("https://www.etsy.com/")
sb.sleep(1)
search = "FIFA Keychains"
required_text = "keychain"
sb.type('input[data-id="search-query"]', search)
sb.sleep(1)
sb.click('button[aria-label="Search"]')
sb.sleep(2)
sb.click_if_visible('button[aria-label="Ok"]')
endpoint_url = sb.get_endpoint_url()

with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(endpoint_url)
page = browser.contexts[0].pages[0]
items = page.locator("div.v2-listing-card__info")
num = 0
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()
if required_text.lower() in title.lower():
num += 1
title = " ".join(title.split()).strip()
price = price.replace("Sale Price", "").strip().split("\n")[0]
print(f"* <====== {num} ======>")
print(title)
print(price.strip().split("\n")[0])
print(f"*** {num} total items found!")
29 changes: 29 additions & 0 deletions examples/cdp_mode/raw_cdp_etsy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from seleniumbase import sb_cdp

sb = sb_cdp.Chrome(ad_block=True)
sb.goto("https://www.etsy.com/")
sb.sleep(1)
search = "FIFA Keychains"
required_text = "keychain"
sb.type('input[data-id="search-query"]', search)
sb.sleep(1)
sb.click('button[aria-label="Search"]')
sb.sleep(2)
sb.click_if_visible('button[aria-label="Ok"]')
soup = sb.get_beautiful_soup()
items = soup.select("div.v2-listing-card__info")
num = 0
for item in items:
title_element = item.select_one("h3.v2-listing-card__title")
price_element = item.select_one("div.n-listing-card__price")
if title_element and price_element:
title = title_element.get_text()
price = price_element.get_text()
if required_text.lower() in title.lower():
num += 1
title = " ".join(title.split()).strip()
price = price.replace("Sale Price", "").strip().split("\n")[0]
print(f"* <====== {num} ======>")
print(title)
print(price.strip().split("\n")[0])
print(f"*** {num} total items found!")
4 changes: 1 addition & 3 deletions examples/cdp_mode/raw_cdp_nordstrom.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
search = "cocktail dresses for women teal"
sb.press_keys("input#keyword-search-input", search + "\n")
sb.sleep(2.2)
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 @@ -23,4 +20,5 @@
if price:
price_text = price.text
print("* %s (%s)" % (description.text, price_text))
sb.scroll_down(16)
sb.quit()
5 changes: 2 additions & 3 deletions examples/cdp_mode/raw_cdp_zillow.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@
items = sb.find_visible_elements('[data-testid="property-card"]')
print('*** %s:' % search)
for i, item in enumerate(items):
print("<----- %s ----->" % (i + 1))
print(item.query_selector('[data-testid*="price"]').text)
print(f"* <====== {i + 1} ======>")
print(item.query_selector('[data-testid*="details"]').text)
print(item.query_selector('[data-testid*="address"]').text)
print(item.query_selector('[data-testid*="price"]').text)
item.scroll_into_view()
print("<-------------->")
sb.sleep(2)
sb.quit()
16 changes: 16 additions & 0 deletions examples/cdp_mode/raw_indeed_jobs.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, use_chromium=True, incognito=True) as sb:
sb.goto("https://www.indeed.com/?from=gnav-compui")
sb.sleep(0.6)
search = "AI Engineer"
sb.type('input[name="q"]', search)
sb.click('button[type="submit"]')
sb.sleep(3.6)
items = sb.find_visible_elements('[data-testid*="jobcard"]')
print('*** %s:' % search)
for i, item in enumerate(items):
print(f"* <====== {i + 1} ======>")
print(item.text)
item.scroll_into_view()
print(f"*** {len(items)} total items found!")
4 changes: 1 addition & 3 deletions examples/cdp_mode/raw_nordstrom.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@
search = "cocktail dresses for women teal"
sb.press_keys("input#keyword-search-input", search + "\n")
sb.sleep(2.2)
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 @@ -24,3 +21,4 @@
if price:
price_text = price.text
print("* %s (%s)" % (description.text, price_text))
sb.scroll_down(16)
22 changes: 13 additions & 9 deletions examples/cdp_mode/raw_ralphlauren.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@
sb.sleep(2.2)
print("*** Ralph Lauren Search for Dresses:")
unique_item_text = []
items = sb.find_elements('div.product-data')
soup = sb.get_beautiful_soup()
items = soup.select('div.product-data')
for item in items:
description = item.query_selector("a.name-link")
if description and description.text not in unique_item_text:
unique_item_text.append(description.text)
print("* " + description.text)
price = item.query_selector('span[title="Price"]')
if price:
print(" (" + price.text.replace(" ", " ") + ")")
item.scroll_into_view()
description_element = item.select_one("a.name-link")
if description_element:
description_text = description_element.get_text(strip=True)
if description_text not in unique_item_text:
unique_item_text.append(description_text)
print(f"* {description_text}")
price_element = item.select_one('span[title="Price"]')
if price_element:
price_text = " ".join(price_element.get_text().split())
print(f" ({price_text})")
sb.scroll_down(20)
6 changes: 3 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ pip>=26.0.1;python_version<"3.10"
pip>=26.1.2;python_version>="3.10"
packaging>=26.2
setuptools~=70.2;python_version<"3.10"
setuptools>=82.0.1;python_version>="3.10"
setuptools>=83.0.0;python_version>="3.10"
wheel>=0.47.0
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"
filelock~=3.19.1;python_version<"3.10"
filelock>=3.29.5;python_version>="3.10"
filelock>=3.29.6;python_version>="3.10"
fasteners>=0.20
mycdp>=1.4.0
pynose>=1.5.5
Expand All @@ -31,7 +31,7 @@ pyreadline3>=3.5.4;platform_system=="Windows"
tabcompleter>=1.4.1
pdbp>=1.8.2
idna>=3.18
charset-normalizer>=3.4.7,<4
charset-normalizer>=3.4.9,<4
urllib3>=1.26.20,<2;python_version<"3.10"
urllib3>=2.7.0,<3;python_version>="3.10"
requests~=2.32.5;python_version<"3.10"
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.5"
__version__ = "4.50.6"
14 changes: 7 additions & 7 deletions seleniumbase/core/sb_cdp.py
Original file line number Diff line number Diff line change
Expand Up @@ -3446,33 +3446,33 @@ def js_scroll_into_view(self, selector):

def scroll_into_view(self, selector):
self.find_element(selector).scroll_into_view()
self.loop.run_until_complete(self.page.wait(0.1))
self.loop.run_until_complete(self.page.wait(0.05))

def scroll_to_y(self, y):
y = int(y)
js_code = "window.scrollTo(0, %s);" % y
with suppress(Exception):
self.loop.run_until_complete(self.page.evaluate(js_code))
self.loop.run_until_complete(self.page.wait(0.1))
self.loop.run_until_complete(self.page.wait(0.05))

def scroll_by_y(self, y):
y = int(y)
js_code = "window.scrollBy(0, %s);" % y
with suppress(Exception):
self.loop.run_until_complete(self.page.evaluate(js_code))
self.loop.run_until_complete(self.page.wait(0.1))
self.loop.run_until_complete(self.page.wait(0.05))

def scroll_to_top(self):
js_code = "window.scrollTo(0, 0);"
with suppress(Exception):
self.loop.run_until_complete(self.page.evaluate(js_code))
self.loop.run_until_complete(self.page.wait(0.1))
self.loop.run_until_complete(self.page.wait(0.05))

def scroll_to_bottom(self):
js_code = "window.scrollTo(0, 10000);"
with suppress(Exception):
self.loop.run_until_complete(self.page.evaluate(js_code))
self.loop.run_until_complete(self.page.wait(0.1))
self.loop.run_until_complete(self.page.wait(0.05))

def scroll_up(self, amount=25):
"""Scrolls up as a percentage of the page."""
Expand All @@ -3481,7 +3481,7 @@ def scroll_up(self, amount=25):
except Exception:
amount = self.get_window_size()["height"] * amount / 100
self.execute_script("window.scrollBy(0, -%s);" % amount)
self.loop.run_until_complete(self.page.wait(0.1))
self.loop.run_until_complete(self.page.wait(0.05))

def scroll_down(self, amount=25):
"""Scrolls down as a percentage of the page."""
Expand All @@ -3490,7 +3490,7 @@ def scroll_down(self, amount=25):
except Exception:
amount = self.get_window_size()["height"] * amount / 100
self.execute_script("window.scrollBy(0, %s);" % amount)
self.loop.run_until_complete(self.page.wait(0.1))
self.loop.run_until_complete(self.page.wait(0.05))

def save_page_source(self, name, folder=None):
from seleniumbase.core import log_helper
Expand Down
10 changes: 5 additions & 5 deletions seleniumbase/fixtures/base_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -16856,15 +16856,15 @@ def __process_dashboard(self, has_exception, init=False):
'<thead id="results-table-head">'
'<tr style="background-color: #F7F7FD;">'
'<th style="background-color: #FFF8F8; color: #FF2222;">'
'Failed: %s </th>'
'Failed:&nbsp;%s&nbsp;</th>'
'<th style="background-color: #FEFEF9; color: #FFA500;">'
'Skipped: %s </th>'
'Skipped:&nbsp;%s&nbsp;</th>'
'<th style="background-color: #F8FFF8; color: #12A212;">'
'Passed: %s </th>'
'Passed:&nbsp;%s&nbsp;</th>'
'<th style="background-color: #F9F9F9; color: #8C8C8C;">'
'Untested: %s </th>'
'Untested:&nbsp;%s&nbsp;</th>'
'<th style="background-color: #F4F4FF; color: #575792;">'
'Total: %s</th>'
'&nbsp;Total:&nbsp;%s</th>'
"</tr></thead></table>"
"<p></p><div></div>"
'<table border="1px solid #e6e6e6;" width="100%%;" padding: 5px;'
Expand Down
9 changes: 5 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,15 @@
'pip>=26.1.2;python_version>="3.10"',
'packaging>=26.2',
'setuptools~=70.2;python_version<"3.10"', # Newer ones had issues
'setuptools>=82.0.1;python_version>="3.10"',
'setuptools>=83.0.0;python_version>="3.10"',
'wheel>=0.47.0',
'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"',
'filelock~=3.19.1;python_version<"3.10"',
'filelock>=3.29.5;python_version>="3.10"',
'filelock>=3.29.6;python_version>="3.10"',
'fasteners>=0.20',
'mycdp>=1.4.0',
'pynose>=1.5.5',
Expand All @@ -195,7 +195,7 @@
'tabcompleter>=1.4.1',
'pdbp>=1.8.2',
'idna>=3.18',
'charset-normalizer>=3.4.7,<4',
'charset-normalizer>=3.4.9,<4',
'urllib3>=1.26.20,<2;python_version<"3.10"',
'urllib3>=2.7.0,<3;python_version>="3.10"',
'requests~=2.32.5;python_version<"3.10"',
Expand Down Expand Up @@ -275,7 +275,8 @@
'pdfminer.six==20251107;python_version<"3.10"',
'pdfminer.six==20260107;python_version>="3.10"',
'cryptography==49.0.0',
'cffi==2.0.0',
'cffi==2.0.0;python_version<"3.10"',
'cffi==2.1.0;python_version>="3.10"',
'pycparser==2.23;python_version<"3.10"',
'pycparser==3.0;python_version>="3.10"',
],
Expand Down