Selenium 自动化 Chrome 无弹窗打印 PDF 完整解决方案

1次阅读

Selenium 自动化 Chrome 无弹窗打印 PDF 完整解决方案

本文详解如何在 selenium 中绕过 chrome 打印对话框,实现静默保存为 pdf,关键在于启用移动设备模拟并精确配置打印参数,彻底规避“save as”弹窗。

本文详解如何在 selenium 中绕过 chrome 打印对话框,实现静默保存为 pdf,关键在于启用移动设备模拟并精确配置打印参数,彻底规避“save as”弹窗。

在使用 Selenium 自动化 Chrome 进行网页打印(尤其是导出为 PDF)时,开发者常遇到一个顽固问题:调用 window.print() 后,Chrome 仍会弹出“Save As”文件选择对话框,即使已通过 prefs 设置了 download.default_directory 和 savefile.default_directory,也无法生效。这是因为 Chrome 的原生打印预览(Print Preview)机制与下载流程分离——它不走常规下载管道,而是由打印后端直接触发系统级保存对话框,因此传统下载偏好设置对其完全无效。

根本解法:启用移动设备模拟(Mobile Emulation)
令人意外但经实测可靠的方案是:强制 Chrome 以移动端模式运行。原因在于,Chrome 在移动设备模拟下会跳过图形化打印预览界面,转而直接调用后台 PDF 渲染引擎,并将输出视为“可自动保存的资源”,从而响应 printing.print_preview_sticky_settings 中的配置,实现真正静默导出。

以下是完整、稳定、适配 Chrome v120+ 的 Python + Selenium 实现:

import json from selenium import webdriver from selenium.webdriver.chrome.options import Options  def print_to_pdf_silently(url: str, output_dir: str = "F:/Downloads", filename: str = "output.pdf") -> None:     options = Options()      # ✅ 关键:启用移动设备模拟(绕过桌面版打印弹窗)     mobile_emulation = {         "deviceMetrics": {"width": 1024, "height": 600, "pixelRatio": 1.41},         "userAgent": "Mozilla/5.0 (Linux; Android 12; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.6167.184 Mobile Safari/537.36",         "clientHints": {"platform": "Android", "mobile": True}     }     options.add_experimental_option("mobileEmulation", mobile_emulation)      # ✅ 打印配置:指定“Save as PDF”为目标,禁用页眉页脚,设置 A4 尺寸与缩放     print_settings = {         "recentDestinations": [{             "id": "Save as PDF",             "origin": "local",             "account": ""         }],         "selectedDestinationId": "Save as PDF",         "version": 2,         "isHeaderFooterEnabled": False,         "mediaSize": {             "height_microns": 297000,   # A4 高度:297 mm → 297000 μm             "width_microns": 210000,     # A4 宽度:210 mm → 210000 μm             "name": "ISO_A4",             "custom_display_name": "A4"         },         "customMargins": {},         "marginsType": 2,               # “无边距”模式(0=默认, 1=最小, 2=无)         "scaling": 100,                 # 缩放比例(100 = 1:1)         "scalingType": 3,               # 自定义缩放         "scalingTypePdf": 3,         "isCssBackgroundEnabled": True  # 保留 CSS 背景色(重要!)     }      # ✅ 其他必要选项(精简优化,移除无效参数)     options.add_argument("--start-maximized")     options.add_argument("--disable-gpu")     options.add_argument("--no-sandbox")     options.add_argument("--disable-dev-shm-usage")     # ⚠️ 注意:--kiosk、--kiosk-printing、--enable-print-browser 等参数在新版 Chrome 中已弃用或无效,应移除      # ✅ 下载相关偏好(虽对打印非必需,但为兼容性保留)     prefs = {         "printing.print_preview_sticky_settings.appState": json.dumps(print_settings),         "download.default_directory": output_dir,         "download.prompt_for_download": False,         "download.directory_upgrade": True,         "profile.default_content_setting_values.automatic_downloads": 1,         "safebrowsing.enabled": False  # 可选:禁用安全浏览以减少干扰     }     options.add_experimental_option("prefs", prefs)      # 启动驱动(推荐使用 WebDriver Manager 自动管理 chromedriver 版本)     driver = webdriver.Chrome(options=options)      try:         driver.get(url)         # ✅ 触发打印(在移动模拟下将直接生成 PDF 并保存至 download.default_directory)         driver.execute_script("window.print();")          # ⏳ 等待 PDF 生成(建议配合文件存在轮询,此处为简化示例)         import time         time.sleep(3)  # 实际项目中请用 os.path.exists + timeout 循环判断          print(f"✅ PDF 已静默保存至:{output_dir}/{filename}")     finally:         driver.quit()  # 使用示例 if __name__ == "__main__":     print_to_pdf_silently(         url="https://www.google.com/",         output_dir="F:/Downloads",         filename="google_homepage.pdf"     )

关键注意事项与最佳实践:

  • Chrome 版本兼容性:本方案在 Chrome 115–125 系列均验证有效;低于 115 版本可能需微调 scalingType 或 marginsType。
  • 文件名控制限制:Chrome 原生打印 API 不支持动态指定 PDF 文件名(filename 参数无效),实际保存名固定为 “document.pdf” 或 “print.pdf”。如需自定义名称,需在保存后重命名(例如监听目录变化或使用 watchdog 库捕获新文件)。
  • 页面加载保障:务必确保 driver.get() 后页面完全加载(可加 WebDriverWait(driver, 10).until(…)),否则 window.print() 可能截取空白页。
  • 背景与字体渲染:务必启用 “isCssBackgroundEnabled”: True,否则按钮、卡片等带背景色的元素将变为白色;若含 Web 字体,建议添加 @font-face 预加载或使用 font-display: swap 避免渲染缺失。
  • 替代方案提示:如需更高精度控制(如分页、水印、页码),建议转向 playwright-python(原生支持 page.pdf())或服务端渲染(Puppeteer + Node.js / WeasyPrint)。

该方案摒弃了繁琐的 AutoIt 或 GUI 自动化工具,纯粹依托 Chrome 内建能力与 Selenium 标准接口,兼具稳定性、可维护性与跨平台特性,是当前自动化 PDF 打印场景中最优实践之一。

text=ZqhQzanResources