Skip to content

Commit a76dab4

Browse files
authored
Merge pull request #3328 from seleniumbase/cdp-mode-patch-17
CDP Mode - Patch 17
2 parents d200f49 + 0cf3609 commit a76dab4

17 files changed

+318
-126
lines changed

examples/cdp_mode/raw_albertsons.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@
2424
info_selector = 'span[data-test-id*="recipe-thumb-title"]'
2525
items = sb.cdp.find_elements("%s %s" % (item_selector, info_selector))
2626
for item in items:
27-
sb.sleep(0.03)
28-
item.scroll_into_view()
29-
sb.sleep(0.025)
27+
sb.sleep(0.06)
3028
if required_text in item.text:
3129
item.flash(color="44CC88")
3230
sb.sleep(0.025)

examples/cdp_mode/raw_cf.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""Using CDP Mode with PyAutoGUI to bypass CAPTCHAs."""
2+
from seleniumbase import SB
3+
4+
with SB(uc=True, test=True, locale_code="en") as sb:
5+
url = "https://www.cloudflare.com/login"
6+
sb.activate_cdp_mode(url)
7+
sb.sleep(2)
8+
sb.uc_gui_handle_captcha() # PyAutoGUI press Tab and Spacebar
9+
sb.sleep(2)
10+
11+
with SB(uc=True, test=True, locale_code="en") as sb:
12+
url = "https://www.cloudflare.com/login"
13+
sb.activate_cdp_mode(url)
14+
sb.sleep(2)
15+
sb.uc_gui_click_captcha() # PyAutoGUI click. (Linux needs it)
16+
sb.sleep(2)

examples/cdp_mode/raw_nordstrom.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
sb.sleep(2.2)
1212
for i in range(16):
1313
sb.cdp.scroll_down(16)
14-
sb.sleep(0.16)
14+
sb.sleep(0.14)
1515
print('*** Nordstrom Search for "%s":' % search)
1616
unique_item_text = []
1717
items = sb.cdp.find_elements("article")

examples/cdp_mode/raw_pixelscan.py

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from seleniumbase import SB
2+
3+
with SB(uc=True, incognito=True, test=True) as sb:
4+
sb.activate_cdp_mode("https://pixelscan.net/")
5+
sb.sleep(3)
6+
sb.remove_elements("div.banner") # Remove the banner
7+
sb.remove_elements("jdiv") # Remove chat widgets
8+
sb.cdp.scroll_down(15)
9+
not_masking_text = "You are not masking your fingerprint"
10+
sb.assert_text(not_masking_text, "pxlscn-fingerprint-masking")
11+
no_automation_detected = "No automation framework detected"
12+
sb.assert_text(no_automation_detected, "pxlscn-bot-detection")
13+
sb.highlight("span.text-success", loops=8)
14+
sb.sleep(1)
15+
fingerprint_masking_div = "pxlscn-fingerprint-masking div"
16+
sb.highlight(fingerprint_masking_div, loops=9)
17+
sb.sleep(1)
18+
sb.highlight(".bot-detection-context", loops=10)
19+
sb.sleep(2)

examples/cdp_mode/raw_res_nike.py

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"""Using CDP.network.RequestWillBeSent and CDP.network.ResponseReceived."""
2+
import colorama
3+
import mycdp
4+
import sys
5+
from seleniumbase import SB
6+
7+
c1 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
8+
c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
9+
cr = colorama.Style.RESET_ALL
10+
if "linux" in sys.platform:
11+
c1 = c2 = cr = ""
12+
13+
14+
async def send_handler(event: mycdp.network.RequestWillBeSent):
15+
r = event.request
16+
s = f"{r.method} {r.url}"
17+
for k, v in r.headers.items():
18+
s += f"\n\t{k} : {v}"
19+
print(c1 + "*** ==> RequestWillBeSent <== ***" + cr)
20+
print(s)
21+
22+
23+
async def receive_handler(event: mycdp.network.ResponseReceived):
24+
print(c2 + "*** ==> ResponseReceived <== ***" + cr)
25+
print(event.response)
26+
27+
28+
with SB(uc=True, test=True, locale_code="en", ad_block=True) as sb:
29+
url = "https://www.nike.com/"
30+
sb.activate_cdp_mode(url)
31+
sb.cdp.add_handler(mycdp.network.RequestWillBeSent, send_handler)
32+
sb.cdp.add_handler(mycdp.network.ResponseReceived, receive_handler)
33+
sb.sleep(2.5)
34+
sb.cdp.gui_click_element('div[data-testid="user-tools-container"]')
35+
sb.sleep(1.5)
36+
search = "Nike Air Force 1"
37+
sb.cdp.press_keys('input[type="search"]', search)
38+
sb.sleep(4)
39+
elements = sb.cdp.select_all('ul[data-testid*="products"] figure .details')
40+
if elements:
41+
print('**** Found results for "%s": ****' % search)
42+
for element in elements:
43+
print("* " + element.text)
44+
sb.sleep(2)

examples/cdp_mode/raw_tiktok.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
print(sb.cdp.get_text('h2[data-e2e="user-bio"]'))
1212
for i in range(55):
1313
sb.cdp.scroll_down(12)
14-
sb.sleep(0.06)
14+
sb.sleep(0.05)
1515
sb.sleep(1)

examples/raw_pixelscan.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from seleniumbase import SB
22

33
with SB(uc=True, incognito=True, test=True) as sb:
4-
sb.driver.uc_open_with_reconnect("https://pixelscan.net/", 10)
4+
sb.driver.uc_open_with_reconnect("https://pixelscan.net/", 7)
55
sb.remove_elements("div.banner") # Remove the banner
66
sb.remove_elements("jdiv") # Remove chat widgets
77
no_automation_detected = "No automation framework detected"

seleniumbase/__version__.py

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

seleniumbase/core/browser_launcher.py

+47-27
Original file line numberDiff line numberDiff line change
@@ -1413,7 +1413,7 @@ def _uc_gui_handle_captcha_(driver, frame="iframe", ctype=None):
14131413
ctype = "cf_t"
14141414
else:
14151415
return
1416-
if not driver.is_connected():
1416+
if not driver.is_connected() and not __is_cdp_swap_needed(driver):
14171417
driver.connect()
14181418
time.sleep(2)
14191419
install_pyautogui_if_missing(driver)
@@ -1425,15 +1425,18 @@ def _uc_gui_handle_captcha_(driver, frame="iframe", ctype=None):
14251425
)
14261426
with gui_lock: # Prevent issues with multiple processes
14271427
needs_switch = False
1428-
is_in_frame = js_utils.is_in_frame(driver)
1428+
if not __is_cdp_swap_needed(driver):
1429+
is_in_frame = js_utils.is_in_frame(driver)
1430+
else:
1431+
is_in_frame = False
14291432
selector = "#challenge-stage"
14301433
if ctype == "g_rc":
14311434
selector = "#recaptcha-token"
14321435
if is_in_frame and driver.is_element_present(selector):
14331436
driver.switch_to.parent_frame()
14341437
needs_switch = True
14351438
is_in_frame = js_utils.is_in_frame(driver)
1436-
if not is_in_frame:
1439+
if not is_in_frame and not __is_cdp_swap_needed(driver):
14371440
# Make sure the window is on top
14381441
page_actions.switch_to_window(
14391442
driver, driver.current_window_handle, 2, uc_lock=False
@@ -1500,17 +1503,18 @@ def _uc_gui_handle_captcha_(driver, frame="iframe", ctype=None):
15001503
and frame == "iframe"
15011504
):
15021505
frame = 'iframe[title="reCAPTCHA"]'
1503-
if not is_in_frame or needs_switch:
1504-
# Currently not in frame (or nested frame outside CF one)
1505-
try:
1506-
if visible_iframe or ctype == "g_rc":
1507-
driver.switch_to_frame(frame)
1508-
except Exception:
1509-
if visible_iframe or ctype == "g_rc":
1510-
if driver.is_element_present("iframe"):
1511-
driver.switch_to_frame("iframe")
1512-
else:
1513-
return
1506+
if not __is_cdp_swap_needed(driver):
1507+
if not is_in_frame or needs_switch:
1508+
# Currently not in frame (or nested frame outside CF one)
1509+
try:
1510+
if visible_iframe or ctype == "g_rc":
1511+
driver.switch_to_frame(frame)
1512+
except Exception:
1513+
if visible_iframe or ctype == "g_rc":
1514+
if driver.is_element_present("iframe"):
1515+
driver.switch_to_frame("iframe")
1516+
else:
1517+
return
15141518
try:
15151519
selector = "div.cf-turnstile"
15161520
if ctype == "g_rc":
@@ -1526,11 +1530,11 @@ def _uc_gui_handle_captcha_(driver, frame="iframe", ctype=None):
15261530
tab_count += 1
15271531
time.sleep(0.027)
15281532
active_element_css = js_utils.get_active_element_css(driver)
1529-
print(active_element_css)
15301533
if (
15311534
active_element_css.startswith(selector)
15321535
or active_element_css.endswith(" > div" * 2)
15331536
or (special_form and active_element_css.endswith(" div"))
1537+
or (ctype == "g_rc" and "frame[name" in active_element_css)
15341538
):
15351539
found_checkbox = True
15361540
sb_config._saved_cf_tab_count = tab_count
@@ -1550,6 +1554,7 @@ def _uc_gui_handle_captcha_(driver, frame="iframe", ctype=None):
15501554
)
15511555
and hasattr(sb_config, "_saved_cf_tab_count")
15521556
and sb_config._saved_cf_tab_count
1557+
and not __is_cdp_swap_needed(driver)
15531558
):
15541559
driver.uc_open_with_disconnect(driver.current_url, 3.8)
15551560
with suppress(Exception):
@@ -1764,17 +1769,27 @@ def _add_chrome_proxy_extension(
17641769
):
17651770
# Single-threaded
17661771
if zip_it:
1767-
proxy_helper.create_proxy_ext(
1768-
proxy_string, proxy_user, proxy_pass, bypass_list
1769-
)
1770-
proxy_zip = proxy_helper.PROXY_ZIP_PATH
1771-
chrome_options.add_extension(proxy_zip)
1772+
proxy_zip_lock = fasteners.InterProcessLock(PROXY_ZIP_LOCK)
1773+
with proxy_zip_lock:
1774+
proxy_helper.create_proxy_ext(
1775+
proxy_string, proxy_user, proxy_pass, bypass_list
1776+
)
1777+
proxy_zip = proxy_helper.PROXY_ZIP_PATH
1778+
chrome_options.add_extension(proxy_zip)
17721779
else:
1773-
proxy_helper.create_proxy_ext(
1774-
proxy_string, proxy_user, proxy_pass, bypass_list, zip_it=False
1775-
)
1776-
proxy_dir_path = proxy_helper.PROXY_DIR_PATH
1777-
chrome_options = add_chrome_ext_dir(chrome_options, proxy_dir_path)
1780+
proxy_dir_lock = fasteners.InterProcessLock(PROXY_DIR_LOCK)
1781+
with proxy_dir_lock:
1782+
proxy_helper.create_proxy_ext(
1783+
proxy_string,
1784+
proxy_user,
1785+
proxy_pass,
1786+
bypass_list,
1787+
zip_it=False,
1788+
)
1789+
proxy_dir_path = proxy_helper.PROXY_DIR_PATH
1790+
chrome_options = add_chrome_ext_dir(
1791+
chrome_options, proxy_dir_path
1792+
)
17781793
else:
17791794
# Multi-threaded
17801795
if zip_it:
@@ -1803,7 +1818,7 @@ def _add_chrome_proxy_extension(
18031818
proxy_user,
18041819
proxy_pass,
18051820
bypass_list,
1806-
False,
1821+
zip_it=False,
18071822
)
18081823
chrome_options = add_chrome_ext_dir(
18091824
chrome_options, proxy_helper.PROXY_DIR_PATH
@@ -4845,7 +4860,12 @@ def get_local_driver(
48454860
)
48464861
uc_activated = True
48474862
except URLError as e:
4848-
if cert in e.args[0] and IS_MAC:
4863+
if (
4864+
IS_MAC
4865+
and hasattr(e, "args")
4866+
and isinstance(e.args, (list, tuple))
4867+
and cert in e.args[0]
4868+
):
48494869
mac_certificate_error = True
48504870
else:
48514871
raise

seleniumbase/core/log_helper.py

+10-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from seleniumbase import config as sb_config
88
from seleniumbase.config import settings
99
from seleniumbase.fixtures import constants
10+
from seleniumbase.fixtures import shared_utils
1011

1112
python3_11_or_newer = False
1213
if sys.version_info >= (3, 11):
@@ -33,6 +34,8 @@ def log_screenshot(test_logpath, driver, screenshot=None, get=False):
3334
if screenshot != screenshot_warning:
3435
with open(screenshot_path, "wb") as file:
3536
file.write(screenshot)
37+
with suppress(Exception):
38+
shared_utils.make_writable(screenshot_path)
3639
else:
3740
print("WARNING: %s" % screenshot_warning)
3841
if get:
@@ -282,13 +285,14 @@ def log_test_failure_data(test, test_logpath, driver, browser, url=None):
282285
sb_config._report_time = the_time
283286
sb_config._report_traceback = traceback_message
284287
sb_config._report_exception = exc_message
285-
with suppress(Exception):
286-
if not os.path.exists(test_logpath):
288+
if not os.path.exists(test_logpath):
289+
with suppress(Exception):
287290
os.makedirs(test_logpath)
288291
with suppress(Exception):
289292
log_file = codecs.open(basic_file_path, "w+", encoding="utf-8")
290293
log_file.writelines("\r\n".join(data_to_save))
291294
log_file.close()
295+
shared_utils.make_writable(basic_file_path)
292296

293297

294298
def log_skipped_test_data(test, test_logpath, driver, browser, reason):
@@ -343,6 +347,7 @@ def log_skipped_test_data(test, test_logpath, driver, browser, reason):
343347
log_file = codecs.open(file_path, "w+", encoding="utf-8")
344348
log_file.writelines("\r\n".join(data_to_save))
345349
log_file.close()
350+
shared_utils.make_writable(file_path)
346351

347352

348353
def log_page_source(test_logpath, driver, source=None):
@@ -365,14 +370,15 @@ def log_page_source(test_logpath, driver, source=None):
365370
"unresponsive, or closed prematurely!</h4>"
366371
)
367372
)
368-
with suppress(Exception):
369-
if not os.path.exists(test_logpath):
373+
if not os.path.exists(test_logpath):
374+
with suppress(Exception):
370375
os.makedirs(test_logpath)
371376
html_file_path = os.path.join(test_logpath, html_file_name)
372377
with suppress(Exception):
373378
html_file = codecs.open(html_file_path, "w+", encoding="utf-8")
374379
html_file.write(page_source)
375380
html_file.close()
381+
shared_utils.make_writable(html_file_path)
376382

377383

378384
def get_test_id(test):

0 commit comments

Comments
 (0)