Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 6e4b5f5

Browse files
authoredMar 22, 2025··
Merge pull request #3624 from seleniumbase/cdp-mode-patch-43
CDP Mode: Patch 43
2 parents 0b9852f + 3d12e02 commit 6e4b5f5

File tree

6 files changed

+61
-8
lines changed

6 files changed

+61
-8
lines changed
 

‎examples/cdp_mode/ReadMe.md

+1
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ sb.cdp.scroll_to_bottom()
512512
sb.cdp.scroll_up(amount=25)
513513
sb.cdp.scroll_down(amount=25)
514514
sb.cdp.save_screenshot(name, folder=None, selector=None)
515+
sb.cdp.print_to_pdf(name, folder=None)
515516
```
516517

517518
--------

‎seleniumbase/__version__.py

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

‎seleniumbase/core/browser_launcher.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import fasteners
2+
import json
23
import logging
34
import os
45
import platform
@@ -769,6 +770,7 @@ def uc_open_with_cdp_mode(driver, url=None):
769770
cdp.scroll_up = CDPM.scroll_up
770771
cdp.scroll_down = CDPM.scroll_down
771772
cdp.save_screenshot = CDPM.save_screenshot
773+
cdp.print_to_pdf = CDPM.print_to_pdf
772774
cdp.page = page # async world
773775
cdp.driver = driver.cdp_base # async world
774776
cdp.tab = cdp.page # shortcut (original)
@@ -2125,6 +2127,15 @@ def _set_chrome_options(
21252127
prefs["enable_do_not_track"] = True
21262128
if external_pdf:
21272129
prefs["plugins.always_open_pdf_externally"] = True
2130+
pdf_settings = {
2131+
"recentDestinations": [
2132+
{"id": "Save as PDF", "origin": "local", "account": ""}
2133+
],
2134+
"selectedDestinationId": "Save as PDF",
2135+
"version": 2,
2136+
}
2137+
app_state = "printing.print_preview_sticky_settings.appState"
2138+
prefs[app_state] = json.dumps(pdf_settings)
21282139
if proxy_string or proxy_pac_url:
21292140
# Implementation of https://stackoverflow.com/q/65705775/7058266
21302141
prefs["webrtc.ip_handling_policy"] = "disable_non_proxied_udp"
@@ -3299,7 +3310,6 @@ def get_remote_driver(
32993310
from seleniumbase.core import capabilities_parser
33003311
desired_caps = capabilities_parser.get_desired_capabilities(cap_file)
33013312
if cap_string:
3302-
import json
33033313
try:
33043314
extra_caps = json.loads(str(cap_string))
33053315
except Exception as e:

‎seleniumbase/core/sb_cdp.py

+6
Original file line numberDiff line numberDiff line change
@@ -2181,6 +2181,12 @@ def save_screenshot(self, name, folder=None, selector=None):
21812181
else:
21822182
self.select(selector).save_screenshot(filename)
21832183

2184+
def print_to_pdf(self, name, folder=None):
2185+
filename = name
2186+
if folder:
2187+
filename = os.path.join(folder, name)
2188+
self.loop.run_until_complete(self.page.print_to_pdf(filename))
2189+
21842190

21852191
class Chrome(CDPMethods):
21862192
def __init__(self, url=None, **kwargs):

‎seleniumbase/undetected/__init__.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,9 @@ def reconnect(self, timeout=0.1):
459459
if self.current_url.startswith(
460460
"chrome-extension://"
461461
):
462-
self.close()
462+
# https://issues.chromium.org/issues/396611138
463+
# (Uncomment below when resolved)
464+
# self.close()
463465
if self.service.is_connectable():
464466
self.stop_client()
465467
self.service.stop()
@@ -496,7 +498,9 @@ def connect(self):
496498
if self.current_url.startswith(
497499
"chrome-extension://"
498500
):
499-
self.close()
501+
# https://issues.chromium.org/issues/396611138
502+
# (Uncomment below when resolved)
503+
# self.close()
500504
if self.service.is_connectable():
501505
self.stop_client()
502506
self.service.stop()

‎seleniumbase/undetected/cdp_driver/tab.py

+36-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
from __future__ import annotations
22
import asyncio
3+
import base64
4+
import datetime
35
import logging
46
import pathlib
7+
import urllib.parse
58
import warnings
69
from typing import Dict, List, Union, Optional, Tuple
710
from . import browser as cdp_browser
@@ -1133,9 +1136,6 @@ async def save_screenshot(
11331136
:return: The path/filename of the saved screenshot.
11341137
:rtype: str
11351138
"""
1136-
import urllib.parse
1137-
import datetime
1138-
11391139
await self.sleep() # Update the target's URL
11401140
path = None
11411141
if format.lower() in ["jpg", "jpeg"]:
@@ -1166,8 +1166,40 @@ async def save_screenshot(
11661166
"Most possible cause is the page "
11671167
"has not finished loading yet."
11681168
)
1169-
import base64
1169+
data_bytes = base64.b64decode(data)
1170+
if not path:
1171+
raise RuntimeError("Invalid filename or path: '%s'" % filename)
1172+
path.write_bytes(data_bytes)
1173+
return str(path)
11701174

1175+
async def print_to_pdf(
1176+
self,
1177+
filename: Optional[PathLike] = "auto",
1178+
) -> str:
1179+
"""
1180+
Saves a webpage as a PDF.
1181+
:param filename: uses this as the save path
1182+
:type filename: PathLike
1183+
:return: The path/filename of the saved screenshot.
1184+
:rtype: str
1185+
"""
1186+
await self.sleep() # Update the target's URL
1187+
path = None
1188+
ext = ".pdf"
1189+
if not filename or filename == "auto":
1190+
parsed = urllib.parse.urlparse(self.target.url)
1191+
parts = parsed.path.split("/")
1192+
last_part = parts[-1]
1193+
last_part = last_part.rsplit("?", 1)[0]
1194+
dt_str = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
1195+
candidate = f"{parsed.hostname}__{last_part}_{dt_str}"
1196+
path = pathlib.Path(candidate + ext) # noqa
1197+
else:
1198+
path = pathlib.Path(filename)
1199+
path.parent.mkdir(parents=True, exist_ok=True)
1200+
data, _ = await self.send(cdp.page.print_to_pdf())
1201+
if not data:
1202+
raise ProtocolException("Could not save PDF.")
11711203
data_bytes = base64.b64decode(data)
11721204
if not path:
11731205
raise RuntimeError("Invalid filename or path: '%s'" % filename)

0 commit comments

Comments
 (0)
Please sign in to comment.