Chrome扩展Selenium4测试:如何访问内容脚本创建的Closed Shadow Root
解决方案:访问Chrome扩展中的Closed Shadow Root并验证元素
一、把Closed Shadow Root改成Open(有权限情况下)
既然你有测试所需的全部权限,最直接的办法就是修改扩展内容脚本的代码,把创建shadow root的模式从closed改成open:
- 找到扩展里创建shadow root的代码,比如原来写的是
element.attachShadow({mode: 'closed'}) - 直接改成
element.attachShadow({mode: 'open'}) - 重新打包扩展,用Selenium加载修改后的扩展包,之后就能通过
element.shadowRoot直接访问shadow root内部的元素,正常用Selenium的定位方法做验证。
要是不想改原扩展代码,也可以通过Chrome DevTools Protocol(CDP)注入脚本,在shadow root创建前拦截并修改模式:
- 用Selenium的CDP接口执行这段脚本,覆盖原生的
attachShadow方法:
driver.execute_cdp_cmd("Runtime.evaluate", { "expression": """ Element.prototype.attachShadow = function(options) { options.mode = 'open'; return Reflect.apply(HTMLElement.prototype.attachShadow, this, [options]); }; """, "world": "MAIN" # 确保注入到扩展内容脚本的上下文里 })
- 刷新页面或者触发扩展内容脚本执行,之后新创建的shadow root都会是open模式,后续就能正常访问了。
二、直接访问Closed Shadow Root(不用改模式)
如果不想修改shadow root的模式,借助Chrome DevTools Protocol的DOM快照功能,就能获取包含closed shadow root的完整DOM结构,刚好满足你只读取数据的需求:
- 通过CDP获取页面的完整DOM快照:
snapshot = driver.execute_cdp_cmd("DOM.getSnapshot", { "includeShadowDOM": True, "includeUserAgentShadowDOM": False })
- 解析快照里的节点数据,提取closed shadow root内部的元素信息,或者直接生成HTML字符串:
# 从快照构建HTML的简单示例,可根据自己的需求完善 def build_html_from_snapshot(nodes): html = "" for node in nodes: if node.get("nodeType") == 1: # 元素节点 tag = node["nodeName"].lower() attrs = " ".join([f'{k}="{v}"' for k, v in node.get("attributes", {}).items()]) html += f"<{tag} {attrs}>" if "children" in node: html += build_html_from_snapshot(node["children"]) html += f"</{tag}>" elif node.get("nodeType") == 3: # 文本节点 html += node["nodeValue"] return html full_html = build_html_from_snapshot(snapshot["domNodes"])
- 把生成的HTML传入BeautifulSoup解析,就能验证数据了:
from bs4 import BeautifulSoup soup = BeautifulSoup(full_html, "html.parser") # 定位shadow root里的元素并验证数据 target_element = soup.select_one("#shadow-root-element-id") assert target_element.text == "预期的数据内容"
这种方式和Chrome检查器读取closed shadow root的原理一样,能完整获取所有DOM内容,完全适配你只需要读取数据的场景。
内容的提问来源于stack exchange,提问作者Anton Shkurenko
相关产品推荐
相关产品推荐

