You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Selenium用JS定位#shadow-root (open)中PDF下载按钮失败问题

Selenium多层Shadow DOM元素定位报错解决方案

报错原因

你遇到的JavascriptException: Message: javascript error: Cannot read properties of null (reading 'shadowRoot')错误,核心是执行JS查询时,某一层的自定义DOM节点尚未加载完成,querySelector返回了null,读取null的shadowRoot属性触发了报错。
还有两个前置问题也会导致该错误:

  • 点击PDF查看按钮后页面可能新开标签页,你没有切换到对应标签页执行查询
  • 前置步骤的元素定位写法有误,导致流程根本没有走到PDF加载的环节

修复步骤

1. 修复前置步骤的元素定位错误

原代码中driver.find_elements_by_class_name("list_2[href]")写法不符合API规范,class_name方法只能传入纯类名,不能带属性筛选条件,要改为CSS选择器写法:

# 修复前
# url_list = driver.find_elements_by_class_name("list_2[href]")
# 修复后
url_list = driver.find_elements_by_css_selector(".list_2[href]")

2. 确认上下文是否正确

点击view_pdf按钮后如果浏览器新开了PDF预览标签页,需要先切换到新标签页再执行DOM查询:

# 切换到最新打开的标签页
window_handles = driver.window_handles
driver.switch_to.window(window_handles[-1])

3. 增加加载等待+优化穿透JS的鲁棒性

PDF阅读器的自定义元素需要等PDF资源加载完成后才会渲染到DOM树,要增加等待时间,同时JS脚本每一层都做非空判断,避免空指针报错:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 等待PDF页面加载完成,也可以替换为time.sleep(3)做简单测试
WebDriverWait(driver, 10).until(lambda d: d.execute_script("return document.querySelector('pdf-viewer') != null"))

# 逐层穿透shadow DOM,每层做非空校验
download_controls = driver.execute_script("""
// 第一层:找pdf-viewer
const pdfViewer = document.querySelector('pdf-viewer');
if (!pdfViewer) return null;
// 第二层:穿透找viewer-toolbar
const toolbar = pdfViewer.shadowRoot.querySelector('viewer-toolbar');
if (!toolbar) return null;
// 第三层:穿透找下载控件
return toolbar.shadowRoot.querySelector('viewer-download-controls');
""")

if download_controls:
    # 触发下载操作
    download_controls.click()
else:
    print("未找到下载控件,请检查页面结构是否发生变化")

内容的提问来源于stack exchange,提问作者Adam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 04:36:06