Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
使用 Selenium 和 Python 访问 Shadow DOM 中的元素_创想鸟

使用 Selenium 和 Python 访问 Shadow DOM 中的元素

使用 Selenium 和 Python 访问 Shadow DOM 中的元素

本文旨在提供一个全面的教程,指导读者如何使用 selenium 和 python 自动化测试访问和操作 shadow dom 中的元素。由于标准 selenium 方法无法直接穿透 shadow dom,我们将重点介绍如何利用 javascript 执行器获取 shadow root,并在此基础上定位其内部的元素。文章将包含详细的步骤、代码示例以及获取必要信息(如 javascript 路径和 css 选择器)的实用技巧,帮助开发者有效解决 shadow dom 元素的定位难题。

理解 Shadow DOM 及其对自动化测试的挑战

Shadow DOM(影子 DOM)是 Web Components 标准的一部分,它允许开发人员创建封装的、独立的 DOM 子树,这些子树与主文档 DOM 隔离。这种封装性带来了许多好处,例如样式和行为的隔离,防止外部 CSS 规则意外影响组件内部,反之亦然。然而,这种隔离性也给传统的自动化测试工具(如 Selenium)带来了挑战。

当使用 Selenium 的 find_element 方法时,它通常只能在主文档 DOM 中查找元素。对于位于 Shadow DOM 内部的元素,这些方法会失败并抛出 NoSuchElementException,因为它们无法“看到”这些被封装的元素。为了克服这一限制,我们需要借助 JavaScript 执行器来间接访问 Shadow DOM。

访问 Shadow DOM 元素的策略

核心策略是分两步走:首先,通过执行 JavaScript 获取 Shadow DOM 的根节点(Shadow Root);然后,利用这个 Shadow Root 对象作为上下文,在其内部查找目标元素。

步骤一:获取 Shadow Root

要获取 Shadow Root,我们需要知道其宿主元素(Host Element)。宿主元素是主 DOM 中的一个普通元素,Shadow DOM 就依附于它。一旦找到宿主元素,就可以通过其 shadowRoot 属性来访问 Shadow Root。

立即学习“Python免费学习笔记(深入)”;

在 Selenium 中,我们可以使用 driver.execute_script() 方法来执行 JavaScript 代码。获取 Shadow Root 的典型 JavaScript 模式如下:

return document.querySelector('your_host_element_css_selector').shadowRoot;

这里的 ‘your_host_element_css_selector’ 是用于定位 Shadow DOM 宿主元素的 CSS 选择器。

实用技巧:如何获取 Shadow Root 的 JavaScript 路径(Chrome 浏览器)

问小白 问小白

免费使用DeepSeek满血版

问小白 5331 查看详情 问小白 打开 Chrome 开发者工具(F12)。在“Elements”面板中,找到 Shadow DOM 的宿主元素。通常,它会有一个 #shadow-root 的标记。右键点击该宿主元素,选择“Copy” -> “Copy JS path”。复制的 JS path 可能会很长,例如 document.querySelector(“#app > my-component”).shadowRoot。我们需要对其进行一些修改:确保它以 return 开头。将双引号替换为单引号(如果需要,以避免 Python 字符串冲突)。确保路径指向的是 shadowRoot 属性。

示例代码:获取 Shadow Root

from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as EC# 初始化 WebDriverdriver = webdriver.Chrome()driver.get('https://your-target-url.com') # 替换为实际的 URLtry:    # 等待 Shadow DOM 的宿主元素出现    # 假设宿主元素的 CSS 选择器是 '#host-element'    host_element_selector = '#host-element'    WebDriverWait(driver, 10).until(        EC.presence_of_element_located((By.CSS_SELECTOR, host_element_selector))    )    # 通过 JavaScript 获取 Shadow Root    # 这里的 'return document.querySelector("#host-element").shadowRoot' 是一个示例    # 请根据实际页面结构调整 '#host-element'    shadow_root_script = f"return document.querySelector('{host_element_selector}').shadowRoot"    shadow_root = driver.execute_script(shadow_root_script)    if shadow_root:        print("成功获取 Shadow Root。")        # shadow_root 现在是一个 Selenium WebElement 对象,可以像常规元素一样使用    else:        print("未能获取 Shadow Root,宿主元素可能不存在或没有 Shadow DOM。")except Exception as e:    print(f"发生错误: {e}")finally:    # driver.quit() # 暂时不关闭,以便在下一步使用    pass

步骤二:在 Shadow Root 中定位目标元素

一旦获得了 shadow_root 对象,就可以像操作普通的 Selenium WebElement 一样,在其内部使用 find_element 或 find_elements 方法来定位 Shadow DOM 内部的元素。需要注意的是,在 Shadow Root 中,通常推荐使用 CSS 选择器进行定位。

实用技巧:如何获取元素的 CSS 选择器(Chrome 浏览器)

打开 Chrome 开发者工具(F12)。在“Elements”面板中,展开 Shadow DOM 结构,找到你想要定位的目标元素。右键点击该元素,选择“Copy” -> “Copy selector”。复制的 CSS 选择器可以直接用于 By.CSS_SELECTOR。

示例代码:在 Shadow Root 中定位元素

接着上面的代码片段:

# ... (前面的代码,直到获取 shadow_root) ...if shadow_root:    print("成功获取 Shadow Root。")    try:        # 在 Shadow Root 中定位目标元素        # 假设我们要找的是一个 ID 为 "instance" 的 input 元素        # 使用 By.ID 或 By.CSS_SELECTOR 都可以        target_element_in_shadow = shadow_root.find_element(By.ID, "instance")        # 或者 target_element_in_shadow = shadow_root.find_element(By.CSS_SELECTOR, '#instance')        if target_element_in_shadow:            print(f"成功定位到 Shadow DOM 中的元素: {target_element_in_shadow.tag_name}, ID: {target_element_in_shadow.get_attribute('id')}")            # 对定位到的元素进行操作,例如输入文本            target_element_in_shadow.send_keys("Hello Shadow DOM!")            print("已向元素输入文本。")        else:            print("未能在 Shadow Root 中定位到目标元素。")    except Exception as e:        print(f"在 Shadow Root 中定位元素时发生错误: {e}")else:    print("未能获取 Shadow Root,无法在其内部定位元素。")# ... (finally 块,关闭 driver) ...

完整示例代码

将上述步骤整合,形成一个完整的自动化脚本:

from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as EC# 定义目标 URL 和 Shadow DOM 宿主元素的 CSS 选择器# 请根据实际情况修改这些值LOGIN_URL = 'https://sso-login.revelup.com' # 示例 URL,请替换SHADOW_HOST_SELECTOR = '#login-container' # 假设 Shadow DOM 挂载在一个 ID 为 'login-container' 的元素上TARGET_INPUT_ID = 'instance' # Shadow DOM 内部目标 input 元素的 IDdef access_shadow_dom_element(url, shadow_host_selector, target_element_id):    driver = webdriver.Chrome()    driver.get(url)    driver.implicitly_wait(7) # 设置隐式等待,等待元素加载    try:        print(f"尝试访问 URL: {url}")        # 步骤 1: 获取 Shadow Root        # 首先等待 Shadow DOM 的宿主元素出现        print(f"等待 Shadow DOM 宿主元素 ({shadow_host_selector}) 出现...")        WebDriverWait(driver, 15).until(            EC.presence_of_element_located((By.CSS_SELECTOR, shadow_host_selector))        )        print("宿主元素已出现。")        # 构建 JavaScript 脚本来获取 Shadow Root        shadow_root_script = f"return document.querySelector('{shadow_host_selector}').shadowRoot"        shadow_root = driver.execute_script(shadow_root_script)        if shadow_root:            print("成功获取 Shadow Root。")            # 步骤 2: 在 Shadow Root 中定位目标元素            print(f"在 Shadow Root 中定位目标元素 (ID: {target_element_id})...")            # 使用 WebDriverWait 显式等待 Shadow DOM 内部元素出现            target_element = WebDriverWait(shadow_root, 10).until(                EC.presence_of_element_located((By.ID, target_element_id))            )            if target_element:                print(f"成功定位到 Shadow DOM 中的元素: {target_element.tag_name}, ID: {target_element.get_attribute('id')}")                # 对定位到的元素进行操作                target_element.send_keys("MySecretPassword")                print("已向目标元素输入文本。")                # 示例:获取输入框的值                print(f"输入框当前的值: {target_element.get_attribute('value')}")            else:                print("未能在 Shadow Root 中定位到目标元素。")        else:            print("未能获取 Shadow Root,请检查宿主选择器或页面结构。")    except Exception as e:        print(f"自动化过程中发生错误: {e}")    finally:        print("关闭 WebDriver。")        driver.quit()# 调用函数执行自动化流程if __name__ == "__main__":    access_shadow_dom_element(LOGIN_URL, SHADOW_HOST_SELECTOR, TARGET_INPUT_ID)

注意事项与总结

CSS 选择器是关键: 在 Shadow DOM 中定位元素时,CSS 选择器是最可靠和推荐的方法。确保你获取的 CSS 选择器是准确且唯一的。等待机制: 即使使用了 implicitly_wait,也强烈建议对 Shadow DOM 的宿主元素和 Shadow DOM 内部的元素使用 WebDriverWait 进行显式等待。这可以避免在元素尚未完全加载时尝试定位而导致的错误。JavaScript 路径的准确性: 获取 Shadow Root 的 JavaScript 路径必须非常精确。任何微小的错误都可能导致 execute_script 返回 None 或抛出 JavaScript 错误。嵌套 Shadow DOM: 如果存在多层嵌套的 Shadow DOM,你需要逐层获取 Shadow Root。例如,先获取第一层 Shadow Root,然后在这个 Shadow Root 对象上执行 JavaScript 来获取第二层 Shadow Root,以此类推。跨浏览器兼容性: 虽然本文主要以 Chrome 为例,但这种通过 execute_script 访问 shadowRoot 的方法在支持 Shadow DOM 的现代浏览器中通常是通用的。

通过掌握上述方法,你可以有效地使用 Selenium 和 Python 应对 Shadow DOM 带来的自动化挑战,确保测试脚本能够稳定地与现代 Web 应用进行交互。

以上就是使用 Selenium 和 Python 访问 Shadow DOM 中的元素的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/593439.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
苹果内存有几种
上一篇 2025年11月10日 17:00:27
Mac玩‎《奇妙料理餐厅》教程:苹果电脑畅玩iOS手游攻略
下一篇 2025年11月10日 17:00:30

相关推荐

  • 即梦AI运镜控制怎么控制_即梦AI视频镜头移动技巧详解

    掌握即梦AI运镜需四步:一、用“镜头缓慢推进”等预设提示词生成标准运动;二、通过动效画板框选主体并绘制运动路径;三、设置首尾帧引导转场,实现穿越或循环效果;四、结合“希区柯克式变焦”“时间冻结环绕”等高级技巧增强视觉表现。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 Dee…

    2026年9月21日
    000
  • windows怎么查看电脑型号_Windows查看电脑硬件型号方法

    通过系统信息工具查看:按Win+R输入msinfo32,查找“系统型号”获取电脑型号;2. 使用命令提示符执行wmic csproduct get name查询型号;3. 在Windows 11设置中进入“系统-关于”,查看“设备规格”下的“设备型号”;4. 利用PowerShell运行Get-Wm…

    2026年9月21日
    100
  • Linux如何检查系统中缺失的依赖库

    使用ldd和readelf检查依赖,通过包管理器安装缺失库。ldd显示not found时,用apt-file或yum provides查找并安装对应软件包,必要时添加库路径至/etc/ld.so.conf并运行ldconfig更新缓存。 在Linux系统中,程序运行时依赖各种共享库(.so文件),…

    2026年9月21日
    000
  • .com网站安全维护_保障.com网站稳定的措施

    答案:保障.com网站稳定需加强安全防护、定期备份、实时监控和应急准备。部署防火墙、更新系统、使用HTTPS、限制端口;制定自动备份并异地存储,定期恢复测试;利用监控工具检测可用性与异常流量,优化加载速度;建立应急流程,严格权限管理,定期演练。细节执行到位才能确保长期安全稳定运行。 确保.com网站…

    2026年9月21日
    100
  • 哔哩哔哩怎么设置点赞和投币记录为私密_哔哩哔哩点赞投币隐私设置

    1、进入哔哩哔哩App个人主页,点击头像进入个人空间,通过右上角菜单进入设置;2、开启“隐藏我的点赞”功能,防止他人查看点赞记录;3、在隐私权限设置中关闭“展示投币动态”,限制投币行为的公开显示;4、手动检查并删除或隐藏历史动态中的互动记录,确保过往点赞与投币不被他人可见。 如果您希望在使用哔哩哔哩…

    2026年9月21日
    100
  • 三星电视携手京东开启艺术视听盛典以科技美学重塑家居生活新模式

    三星电视携手京东开启艺术视听盛典以科技美学重塑家居生活新模式三星电视携手京东开启艺术视听盛典以科技美学重塑家居生活新模式三星电视携手京东开启艺术视听盛典以科技美学重塑家居生活新模式三星电视携手京东开启艺术视听盛典以科技美学重塑家居生活新模式

    随着消费理念升级与需求日益多样化,电视已不再仅仅是观看节目和影音娱乐的工具,而是逐渐演变为承载家居美学、传递情感温度、连接智慧生活的艺术载体。在这一变革浪潮中,三星率先引领艺术电视领域的创新风向,theframe画壁艺术电视与theserif画境艺术电视成功打破科技与艺术之间的界限,将电视升华为可观…

    2026年9月21日 • 用户投稿
    100
  • 分布式锁(Redis)解决数据竞争

    使用redis实现分布式锁来解决数据竞争可以通过setnx和expire命令。1)使用setnx尝试获取锁,并通过expire设置锁的过期时间防止死锁。2)释放锁时使用watch命令确保锁未被其他客户端获取。需要注意redis的单点故障、高并发性能瓶颈和锁的过期时间设置。 在处理高并发的应用场景中,…

    2026年9月21日
    000
  • 如何在Weka中处理向量属性:ARFF格式的限制与解决方案

    本文探讨了weka中arff格式对直接向量属性表示的限制,并提供了两种主要解决方案。对于时间序列数据,建议利用weka的内置时间序列分析功能。对于非时间序列数据,核心在于通过特征工程(如使用addexpression、multifilter等)将向量拆解并转换为可被weka有效处理的独立特征,以揭示…

    2026年9月21日
    000
  • 蝴蝶号内容创作不露脸的五大绝技与执行方法 | 快速提升曝光率的实用操作流程

    不露脸也能玩转蝴蝶号内容创作,关键在于将焦点从个人形象转移到内容本身与观众体验上,通过声音叙事、动态文字、手部特写、数据可视化和场景搭建五大核心策略构建吸引力,结合高质量音画配合、精准的受众定位、稳定更新与算法互动,提升曝光率;同时规避素材版权、声音质量与画面单调等技术挑战,善用免费或付费正版素材、…

    2026年9月21日
    100
  • 哪些Docker扩展能让你在VSCode内轻松管理容器?

    Docker官方扩展是VSCode中管理容器的核心工具,提供容器、镜像、卷、网络的可视化操作,结合Remote-Containers可实现容器内开发,辅以YAML、GitLens等扩展提升效率,需确保本地Docker daemon运行。 在 VSCode 中管理 Docker 容器,最核心的扩展是 …

    2026年9月21日
    000
  • windows10如何解决“找不到恢复环境”的问题_windows10恢复环境修复方法

    首先启用恢复环境,若失败则修复BCD引导配置,最后检查并恢复Winre.wim文件以解决“找不到恢复环境”问题。 如果您尝试在Windows 10系统中使用“重置此电脑”或“高级启动”功能,但收到“找不到恢复环境”的提示,则可能是由于恢复环境被禁用、引导配置错误或核心文件丢失。以下是解决此问题的步骤…

    2026年9月21日
    200
  • PostgreSQL地理位置数据按距离排序的最佳实践:数据库层优化策略

    在处理大量地理位置数据并按距离排序时,将排序逻辑下推至数据库层(如postgresql)是更优的选择。这种方法能有效减少应用层的数据传输和内存消耗,充分利用数据库的计算能力,从而提升整体性能和资源利用率,而非在spring boot应用服务层进行排序。 1. 地理位置排序的需求与挑战 在现代Web应…

    2026年9月21日
    100
  • win11系统搜索索引损坏导致搜索缓慢怎么办_Win11搜索索引损坏修复方法

    首先运行搜索和索引疑难解答,然后重启Windows搜索服务;若问题依旧,需重建搜索索引数据库并重置Windows搜索应用组件,最后使用SFC和DISM命令修复系统文件,以彻底解决Windows 11搜索功能响应缓慢或结果不完整的问题。 如果您尝试在Windows 11中使用搜索功能,但发现响应缓慢或…

    2026年9月21日
    000
  • Flyway配置中安全使用环境变量的实践指南

    flyway配置中直接暴露数据库连接参数存在安全隐患。本文详细阐述了如何通过命令行参数和api调用两种主要方式,将环境变量安全地集成到flyway配置流程中。通过外部化管理敏感信息,可以有效提升数据库迁移配置的安全性、灵活性和可维护性,避免将凭证硬编码到配置文件中。 在数据库迁移实践中,将敏感的数据…

    2026年9月21日
    100
  • 如何为VSCode设置最小化到系统托盘?

    VSCode不支持内置最小化到系统托盘功能,可通过第三方工具实现:Windows推荐使用RBTray或AutoHotkey脚本,Linux可借助AppIndicator扩展,macOS则依赖Dock最小化及辅助工具视觉隐藏。 VSCode 本身不提供内置的“最小化到系统托盘”功能,但可以通过一些方法…

    2026年9月21日
    000
  • UC浏览器自带的截图功能快捷键是什么 UC浏览器内置截图快捷键使用说明

    首先通过快捷键或图标触发截图,再选择区域完成截取。UC浏览器支持三种方式:1. 使用Ctrl+Shift+X(Windows)或Command+Shift+X(Mac)快捷键截图;2. 点击地址栏右侧剪刀图标进行全屏、可见区域或自定义截图;3. 在设置中启用手势控制,使用三指下滑手势快速截图。所有截…

    2026年9月21日
    000
  • 怎样在iPhone情侣模式中设置情侣专属表情?个性化聊天的技巧

    怎样在iPhone情侣模式中设置情侣专属表情?个性化聊天的技巧怎样在iPhone情侣模式中设置情侣专属表情?个性化聊天的技巧怎样在iPhone情侣模式中设置情侣专属表情?个性化聊天的技巧怎样在iPhone情侣模式中设置情侣专属表情?个性化聊天的技巧

    通过Memoji、第三方贴纸应用和iOS 16+抠图功能,可为情侣打造专属表情包;结合自定义聊天背景、语音消息、共享相册等方式,既能提升聊天趣味性,又能保持沟通效率,增强情感连接。 在iPhone上设置情侣专属表情,与其说是开启一个内置的“情侣模式”,不如说是巧妙利用iOS系统和第三方应用提供的各种…

    2026年9月21日 • 用户投稿
    100
  • 如何用SumoPaint的AI裁剪图片?快速完成智能图片裁剪教程

    如何用SumoPaint的AI裁剪图片?快速完成智能图片裁剪教程如何用SumoPaint的AI裁剪图片?快速完成智能图片裁剪教程如何用SumoPaint的AI裁剪图片?快速完成智能图片裁剪教程如何用SumoPaint的AI裁剪图片?快速完成智能图片裁剪教程

    答案:SumoPaint虽无AI裁剪功能,但可通过魔棒、套索工具精确选区,结合图层蒙版与羽化、反选等操作实现智能裁剪效果,最后按需导出PNG或JPG高质量文件。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜ 在SumoPaint中,虽然它不…

    2026年9月21日 • 用户投稿
    100
  • Java OOP如何使用内部类提高代码组织性

    内部类提升Java代码组织性与封装性,成员内部类增强封装,静态内部类分离逻辑,局部与匿名内部类简化回调,私有内部类隐藏实现细节。 内部类在Java面向对象编程中是一种有效提升代码组织性和封装性的工具。通过将一个类定义在另一个类的内部,可以更好地表达类之间的逻辑关系,控制访问权限,并减少命名冲突。合理…

    2026年9月21日
    000
  • MySQL缓存机制对性能提升的作用_MySQL缓存配置及调优方案

    MySQL缓存机制对性能提升的作用_MySQL缓存配置及调优方案MySQL缓存机制对性能提升的作用_MySQL缓存配置及调优方案MySQL缓存机制对性能提升的作用_MySQL缓存配置及调优方案MySQL缓存机制对性能提升的作用_MySQL缓存配置及调优方案

    mysql的缓存机制主要包括innodb缓冲池、查询缓存和操作系统文件系统缓存等,其中innodb缓冲池是性能优化的核心。1. innodb缓冲池缓存表数据和索引页,减少磁盘i/o,提升读写效率;2. 查询缓存因失效频繁及锁竞争问题,在高并发场景下易成瓶颈,已在mysql 8.0中移除;3. 操作系…

    2026年9月21日 • 用户投稿
    100

发表回复

登录后才能评论
关注微信