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

Python Selenium爬取施耐德网站遇NoSuchElementException报错求解

Selenium无法定位Shadow DOM内元素问题解决方案

问题原因

你遇到的NoSuchElementException报错核心原因是:普通Selenium定位方法(XPath、CSS选择器等)无法直接穿透#shadow-root (open)边界。该施耐德页面使用了Web Component技术,<product-cards-wrapper>、<product-card>、<product-card-main-info>这类自定义标签都是Shadow DOM的宿主元素,直接跨宿主写XPath是完全找不到内部元素的。
另外你的代码还存在两个额外问题:

  • 绝对XPath过于脆弱,页面DOM结构稍有调整就会失效
  • 翻页按钮的定位使用By.CLASS_NAME传了多类名(带空格),本身也会触发定位失败

解决步骤

1. 逐层穿透Shadow DOM获取元素

Selenium 4.0+已经原生支持Shadow DOM操作,只要逐层获取每个宿主的shadow_root属性,就可以在对应的Shadow DOM树内查找子元素。

2. 改用相对定位+显式等待

替换绝对XPath为更稳定的CSS选择器,使用显式等待替代固定隐式等待,避免元素未加载完成就执行定位。

3. 修复翻页按钮定位逻辑

多类名定位改用CSS选择器格式。

可运行修改代码示例

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 初始化driver
driver = webdriver.Chrome()
driver.implicitly_wait(5)
wait = WebDriverWait(driver, 10)

# 封装穿透Shadow DOM的元素获取工具
def get_shadow_element(parent, selector):
    # parent可以是普通WebElement,也可以是ShadowRoot对象
    if hasattr(parent, 'shadow_root'):
        shadow_root = parent.shadow_root
    else:
        shadow_root = parent
    return wait.until(lambda d: shadow_root.find_element(By.CSS_SELECTOR, selector))

def page_function():
    driver.get('https://www.se.com/us/en/product-range/63426-powerlogic-accusine-pcs%2B/?N=4176697776&No=0&Nrpp=12')
    driver.maximize_window()
    total = 69
    print("Number of products:", total)
    description = []
    unit_price = []
    name = []

    for page in range(0, (total//12)+1):
        # 等待当前页产品列表加载完成
        cards_wrapper = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'product-cards-wrapper')))
        # 穿透第一层shadow root,拿到产品列表
        cards_wrapper_shadow = cards_wrapper.shadow_root
        product_items = wait.until(lambda d: cards_wrapper_shadow.find_elements(By.CSS_SELECTOR, 'ul.product-cards > li'))

        for item in product_items:
            # 穿透product-card的shadow root
            product_card = item.find_element(By.CSS_SELECTOR, 'product-card')
            card_shadow = product_card.shadow_root
            # 穿透product-card-main-info的shadow root
            main_info = card_shadow.find_element(By.CSS_SELECTOR, 'product-card-main-info')
            main_info_shadow = main_info.shadow_root

            # 提取所需字段
            des_ele = main_info_shadow.find_element(By.CSS_SELECTOR, 'pes-router-link:nth-child(2) a h3')
            description.append(des_ele.text)
            name_ele = main_info_shadow.find_element(By.CSS_SELECTOR, 'pes-router-link:nth-child(1) a')
            name.append(name_ele.text)
            # 提取价格
            price_ele = card_shadow.find_element(By.CSS_SELECTOR, 'pes-product-price p span:first-child')
            unit_price.append(price_ele.text)

        # 翻页逻辑
        if len(name) >= total:
            break
        next_btn = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.page-links__arrow.page-links__arrow--next.js-page-link.js-page-link-next')))
        driver.execute_script("arguments[0].click();", next_btn)
        # 等待翻页后内容刷新
        wait.until(EC.staleness_of(cards_wrapper))

    print("名称列表:", name)
    print("描述列表:", description)
    print("价格列表:", unit_price)

if __name__ == '__main__':
    page_function()
    driver.quit()

注意事项

  • 请确保你的Selenium版本升级到4.0以上,低版本不支持原生shadow_root属性操作
  • 代码内的CSS选择器可以根据页面实际结构微调,比绝对XPath稳定性高很多
  • 抓取过程中可以适当增加延迟,避免触发网站反爬机制

内容的提问来源于stack exchange,提问作者Jorge Jurado-Garcia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 07:45:04