Skip to content

Commit d4cde11

Browse files
authored
Merge pull request #3268 from seleniumbase/cdp-mode-patch-10
CDP Mode - Patch 10
2 parents ffdd6c9 + f472788 commit d4cde11

22 files changed

+746
-145
lines changed

examples/cdp_mode/ReadMe.md

+20-4
Original file line numberDiff line numberDiff line change
@@ -323,19 +323,22 @@ sb.cdp.get_active_element_css()
323323
sb.cdp.click(selector)
324324
sb.cdp.click_active_element()
325325
sb.cdp.click_if_visible(selector)
326+
sb.cdp.click_visible_elements(selector)
326327
sb.cdp.mouse_click(selector)
327328
sb.cdp.nested_click(parent_selector, selector)
328329
sb.cdp.get_nested_element(parent_selector, selector)
329-
sb.cdp.flash(selector)
330+
sb.cdp.select_option_by_text(dropdown_selector, option)
331+
sb.cdp.flash(selector, duration=1, color="44CC88", pause=0)
332+
sb.cdp.highlight(selector)
330333
sb.cdp.focus(selector)
331334
sb.cdp.highlight_overlay(selector)
332335
sb.cdp.remove_element(selector)
333336
sb.cdp.remove_from_dom(selector)
334337
sb.cdp.remove_elements(selector)
335-
sb.cdp.scroll_into_view(selector)
336338
sb.cdp.send_keys(selector, text)
337339
sb.cdp.press_keys(selector, text)
338340
sb.cdp.type(selector, text)
341+
sb.cdp.set_value(selector, text)
339342
sb.cdp.evaluate(expression)
340343
sb.cdp.js_dumps(obj_name)
341344
sb.cdp.maximize()
@@ -373,6 +376,11 @@ sb.cdp.gui_press_keys(keys)
373376
sb.cdp.gui_write(text)
374377
sb.cdp.gui_click_x_y(x, y)
375378
sb.cdp.gui_click_element(selector)
379+
sb.cdp.gui_drag_drop_points(x1, y1, x2, y2)
380+
sb.cdp.gui_drag_and_drop(drag_selector, drop_selector)
381+
sb.cdp.gui_hover_x_y(x, y)
382+
sb.cdp.gui_hover_element(selector)
383+
sb.cdp.gui_hover_and_click(hover_selector, click_selector)
376384
sb.cdp.internalize_links()
377385
sb.cdp.is_checked(selector)
378386
sb.cdp.is_selected(selector)
@@ -382,12 +390,20 @@ sb.cdp.uncheck_if_checked(selector)
382390
sb.cdp.unselect_if_selected(selector)
383391
sb.cdp.is_element_present(selector)
384392
sb.cdp.is_element_visible(selector)
385-
sb.cdp.assert_element(selector)
386393
sb.cdp.assert_element_present(selector)
394+
sb.cdp.assert_element_absent(selector)
395+
sb.cdp.assert_element(selector)
396+
sb.cdp.assert_element_visible(selector)
397+
sb.cdp.assert_element_not_visible(selector)
398+
sb.cdp.assert_title(title)
387399
sb.cdp.assert_text(text, selector="html")
388400
sb.cdp.assert_exact_text(text, selector="html")
389-
sb.cdp.scroll_down(amount=25)
401+
sb.cdp.scroll_into_view(selector)
402+
sb.cdp.scroll_to_y(y)
403+
sb.cdp.scroll_to_top()
404+
sb.cdp.scroll_to_bottom()
390405
sb.cdp.scroll_up(amount=25)
406+
sb.cdp.scroll_down(amount=25)
391407
sb.cdp.save_screenshot(name, folder=None, selector=None)
392408
```
393409

examples/cdp_mode/raw_albertsons.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
item.scroll_into_view()
2929
sb.sleep(0.025)
3030
if required_text in item.text:
31-
item.flash()
31+
item.flash(color="44CC88")
3232
sb.sleep(0.025)
3333
if item.text not in unique_item_text:
3434
unique_item_text.append(item.text)

examples/cdp_mode/raw_browserscan.py

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from seleniumbase import SB
2+
3+
with SB(uc=True, test=True, ad_block=True) as sb:
4+
url = "https://www.browserscan.net/bot-detection"
5+
sb.activate_cdp_mode(url)
6+
sb.sleep(1)
7+
sb.cdp.flash("Test Results", duration=4)
8+
sb.sleep(1)
9+
sb.cdp.assert_element('strong:contains("Normal")')
10+
sb.cdp.flash('strong:contains("Normal")', duration=4, pause=4)

examples/cdp_mode/raw_cdp_with_sb.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
with SB(uc=True, test=True, locale_code="en") as sb:
77
url = "https://www.priceline.com/"
88
sb.activate_cdp_mode(url)
9-
sb.sleep(3)
9+
sb.sleep(2.5)
1010
sb.internalize_links() # Don't open links in a new tab
1111
sb.click("#link_header_nav_experiences")
1212
sb.sleep(2.5)

examples/cdp_mode/raw_footlocker.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
with SB(uc=True, test=True, locale_code="en") as sb:
44
url = "https://www.footlocker.com/"
55
sb.activate_cdp_mode(url)
6-
sb.sleep(3)
6+
sb.sleep(2.5)
77
sb.cdp.click_if_visible('button[id*="Agree"]')
88
sb.sleep(1.5)
99
sb.cdp.mouse_click('input[aria-label="Search"]')

examples/cdp_mode/raw_nike.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
with SB(uc=True, test=True, locale_code="en") as sb:
44
url = "https://www.nike.com/"
55
sb.activate_cdp_mode(url)
6-
sb.sleep(3)
6+
sb.sleep(2.5)
77
sb.cdp.gui_click_element('div[data-testid="user-tools-container"]')
88
sb.sleep(1.5)
99
search = "Nike Air Force 1"

examples/cdp_mode/raw_planetmc.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
with SB(uc=True, test=True, locale_code="en") as sb:
44
url = "www.planetminecraft.com/account/sign_in/"
55
sb.activate_cdp_mode(url)
6-
sb.sleep(1)
7-
sb.cdp.gui_click_element("#turnstile-widget")
6+
sb.sleep(2)
7+
sb.cdp.gui_click_element("#turnstile-widget div")
88
sb.sleep(2)

examples/cdp_mode/raw_pokemon.py

+9-7
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,24 @@
33
with SB(uc=True, test=True, locale_code="en") as sb:
44
url = "https://www.pokemon.com/us"
55
sb.activate_cdp_mode(url)
6-
sb.sleep(3)
6+
sb.sleep(2.5)
77
sb.cdp.click_if_visible("button#onetrust-reject-all-handler")
8-
sb.sleep(1)
8+
sb.sleep(1.2)
99
sb.cdp.click('a[href="https://www.pokemon.com/us/pokedex/"]')
10-
sb.sleep(1)
10+
sb.sleep(1.2)
1111
sb.cdp.click('b:contains("Show Advanced Search")')
12-
sb.sleep(1)
12+
sb.sleep(1.2)
1313
sb.cdp.click('span[data-type="type"][data-value="electric"]')
14-
sb.sleep(1)
14+
sb.sleep(0.5)
15+
sb.scroll_into_view("a#advSearch")
16+
sb.sleep(0.5)
1517
sb.cdp.click("a#advSearch")
16-
sb.sleep(1)
18+
sb.sleep(1.2)
1719
sb.cdp.click('img[src*="img/pokedex/detail/025.png"]')
1820
sb.cdp.assert_text("Pikachu", 'div[class*="title"]')
1921
sb.cdp.assert_element('img[alt="Pikachu"]')
2022
sb.cdp.scroll_into_view("div.pokemon-ability-info")
21-
sb.sleep(1)
23+
sb.sleep(1.2)
2224
sb.cdp.flash('div[class*="title"]')
2325
sb.cdp.flash('img[alt="Pikachu"]')
2426
sb.cdp.flash("div.pokemon-ability-info")

examples/cdp_mode/raw_priceline.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
window_handle = sb.driver.current_window_handle
55
url = "https://www.priceline.com"
66
sb.activate_cdp_mode(url)
7-
sb.sleep(3)
7+
sb.sleep(2.5)
88
sb.cdp.click('input[name="endLocation"]')
99
sb.sleep(1)
1010
location = "Portland, OR, USA"
@@ -16,14 +16,17 @@
1616
sb.cdp.click(selection)
1717
sb.sleep(1.5)
1818
sb.cdp.click('button[aria-label="Dismiss calendar"]')
19-
sb.sleep(5)
19+
sb.sleep(4.5)
2020
sb.connect()
2121
if len(sb.driver.window_handles) > 1:
2222
sb.switch_to_window(window_handle)
2323
sb.driver.close()
2424
sb.sleep(0.2)
2525
sb.switch_to_newest_window()
2626
sb.sleep(0.6)
27+
for y in range(1, 9):
28+
sb.scroll_to_y(y * 400)
29+
sb.sleep(1.25)
2730
hotel_names = sb.find_elements('a[data-autobot-element-id*="HOTEL_NAME"]')
2831
hotel_prices = sb.find_elements('span[font-size="4,,,5"]')
2932
print("Priceline Hotels in %s:" % location)
@@ -34,4 +37,5 @@
3437
for i, hotel in enumerate(hotel_names):
3538
if hotel_prices[i] and hotel_prices[i].text:
3639
count += 1
37-
print("* %s: %s => %s" % (count, hotel.text, hotel_prices[i].text))
40+
hotel_price = "$" + hotel_prices[i].text
41+
print("* %s: %s => %s" % (count, hotel.text, hotel_price))

examples/cdp_mode/raw_xhr_sb.py

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
"""CDP.network.ResponseReceived with CDP.network.ResourceType.XHR."""
2+
import ast
3+
import asyncio
4+
import colorama
5+
import mycdp
6+
import sys
7+
import time
8+
from seleniumbase.undetected import cdp_driver
9+
10+
xhr_requests = []
11+
last_xhr_request = None
12+
c1 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
13+
c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
14+
cr = colorama.Style.RESET_ALL
15+
if "linux" in sys.platform:
16+
c1 = c2 = cr = ""
17+
18+
19+
def listenXHR(page):
20+
async def handler(evt):
21+
# Get AJAX requests
22+
if evt.type_ is mycdp.network.ResourceType.XHR:
23+
xhr_requests.append([evt.response.url, evt.request_id])
24+
global last_xhr_request
25+
last_xhr_request = time.time()
26+
page.add_handler(mycdp.network.ResponseReceived, handler)
27+
28+
29+
async def receiveXHR(page, requests):
30+
responses = []
31+
retries = 0
32+
max_retries = 5
33+
# Wait at least 2 seconds after last XHR request for more
34+
while True:
35+
if last_xhr_request is None or retries > max_retries:
36+
break
37+
if time.time() - last_xhr_request <= 2:
38+
retries = retries + 1
39+
time.sleep(2)
40+
continue
41+
else:
42+
break
43+
await page
44+
# Loop through gathered requests and get response body
45+
for request in requests:
46+
try:
47+
res = await page.send(mycdp.network.get_response_body(request[1]))
48+
if res is None:
49+
continue
50+
responses.append({
51+
"url": request[0],
52+
"body": res[0],
53+
"is_base64": res[1],
54+
})
55+
except Exception as e:
56+
print("Error getting response:", e)
57+
return responses
58+
59+
60+
async def crawl():
61+
driver = await cdp_driver.cdp_util.start_async()
62+
tab = await driver.get("about:blank")
63+
listenXHR(tab)
64+
65+
# Change url to something that makes ajax requests
66+
tab = await driver.get("https://resttesttest.com/")
67+
time.sleep(1)
68+
# Click AJAX button on https://resttesttest.com/
69+
element = await tab.select("button#submitajax")
70+
await element.click_async()
71+
time.sleep(2)
72+
73+
xhr_responses = await receiveXHR(tab, xhr_requests)
74+
for response in xhr_responses:
75+
print(c1 + "*** ==> XHR Request URL <== ***" + cr)
76+
print(f'{response["url"]}')
77+
is_base64 = response["is_base64"]
78+
b64_data = "Base64 encoded data"
79+
try:
80+
headers = ast.literal_eval(response["body"])["headers"]
81+
print(c2 + "*** ==> XHR Response Headers <== ***" + cr)
82+
print(headers if not is_base64 else b64_data)
83+
except Exception:
84+
response_body = response["body"]
85+
print(c2 + "*** ==> XHR Response Body <== ***" + cr)
86+
print(response_body if not is_base64 else b64_data)
87+
88+
89+
if __name__ == "__main__":
90+
print("================= Starting =================")
91+
loop = asyncio.new_event_loop()
92+
loop.run_until_complete(crawl())

requirements.txt

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
pip>=24.2
22
packaging>=24.2
33
setuptools~=70.2;python_version<"3.10"
4-
setuptools>=73.0.1;python_version>="3.10"
4+
setuptools>=75.5.0;python_version>="3.10"
55
wheel>=0.45.0
66
attrs>=24.2.0
77
certifi>=2024.8.30
88
exceptiongroup>=1.2.2
99
websockets~=13.1;python_version<"3.9"
10-
websockets>=14.0;python_version>="3.9"
10+
websockets>=14.1;python_version>="3.9"
1111
filelock>=3.16.1
1212
fasteners>=0.19
13-
mycdp>=1.0.1
13+
mycdp>=1.1.0
1414
pynose>=1.5.3
1515
platformdirs>=4.3.6
1616
typing-extensions>=4.12.2
@@ -64,7 +64,7 @@ rich==13.9.4
6464
# ("pip install -r requirements.txt" also installs this, but "pip install -e ." won't.)
6565

6666
coverage>=7.6.1;python_version<"3.9"
67-
coverage>=7.6.4;python_version>="3.9"
67+
coverage>=7.6.5;python_version>="3.9"
6868
pytest-cov>=5.0.0;python_version<"3.9"
6969
pytest-cov>=6.0.0;python_version>="3.9"
7070
flake8==5.0.4;python_version<"3.9"

seleniumbase/__version__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# seleniumbase package
2-
__version__ = "4.32.9"
2+
__version__ = "4.32.10"

0 commit comments

Comments
 (0)