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

Selenium代码时灵时不灵的原因及解决方案咨询

问题描述

本人Selenium经验较少,写的代码有时能找到所需元素、有时却报错(提示元素未找到或不可点击)。尝试过ID、XPATH等多种元素定位方式,即便目标元素为HTML静态元素,问题仍反复出现。需求是自动完成巴西央行网站的以下操作:点击“tipo do cliente”→选择PJ→点击CNAE→逐个选择PJ相关活动,点击“Adicionar série”按钮后重复选择活动操作,恳请解决该问题。

现有代码
from selenium import webdriver
import undetected_chromedriver as uc  
from selenium.webdriver.common.by import By    #importa localizadores By
from selenium.webdriver.common.keys import Keys    #importa input para envio de dados
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time   #biblioteca de tempo

driver = uc.Chrome()   #driver alterado para 'undetected'

driver.get('https://www.bcb.gov.br/estabilidadefinanceira/scrdata')
time.sleep(10)

#seleção do tipo do cliente
todos = driver.find_element(By.XPATH, "//div/div[1]/div[1]/div/div[1]/div[2]/ng-select/div/div/div[3]/input")
todos.click()

op2 = driver.find_element(By.ID, "ab2af0cfd2af-2")
op2.click()

#seleção label cnae e adição de serie
time.sleep(2)
cnae = driver.find_element(By.XPATH, "//div/div[3]/bcb-graficoscr/div/div[1]/div[1]/div/div[2]/div[1]/ng-select")
cnae.click()

#passo 1: seleção cnae pj
wait = WebDriverWait(driver, 2)
sel = driver.find_element(By.XPATH, "//div/div[1]/div[1]/div/div[2]/div[1]/ng-select/ng-dropdown-panel/div/div[2]/div[10]")
wait.until(EC.element_to_be_clickable((sel)))
sel.click()

#click botão add
wait1 = WebDriverWait(driver, 2)
btn = driver.find_element(By.XPATH, "//*[contains(text(), 'Adicionar série')]")
wait1.until(EC.element_to_be_clickable((btn)))
btn.click()

time.sleep(3)
#passo 2:
wait1 = WebDriverWait(driver, 2)
sel1 = driver.find_element(By.XPATH, "/html/body/app-root/app-root/div/div/main/dynamic-comp/div/div[3]/bcb-graficoscr/div/div[1]/div[1]/div/div[2]/div[1]/ng-select/ng-dropdown-panel/div/div[2]/div[11]")
wait1.until(EC.element_to_be_clickable((sel1)))
sel.click()


time.sleep(10000)
driver.quit()
解决方案

你的问题核心在于硬编码等待时间不稳定、元素定位路径过于脆弱,以及对ng-select组件的处理方式不当。以下是针对性的修复方案:

1. 替换硬编码sleep为显式等待

完全移除time.sleep(),改用WebDriverWait等待元素加载完成,这是解决元素时有时无问题的关键。

2. 优化元素定位逻辑

避免使用绝对XPATH或依赖索引的路径,改用元素的文本、属性等稳定特征定位:

  • 定位下拉框时,结合ng-select的关联标签文本(如“Tipo do cliente”)
  • 定位选项时,直接通过选项的文本内容匹配,而非固定索引

3. 标准化ng-select组件操作

针对网站使用的Angularng-select组件,封装通用的选择逻辑:点击下拉框→等待面板展开→选择目标选项。

4. 循环处理所有PJ相关活动

提取重复操作逻辑为循环,自动遍历所有PJ类别的CNAE选项,逐个添加。

修改后的完整代码

from selenium import webdriver
import undetected_chromedriver as uc
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import ElementClickInterceptedException

def wait_and_click(driver, locator, timeout=10):
    """封装等待元素可点击并点击的通用函数,处理遮挡问题"""
    element = WebDriverWait(driver, timeout).until(EC.element_to_be_clickable(locator))
    try:
        element.click()
    except ElementClickInterceptedException:
        # 若被遮挡,用JS点击
        driver.execute_script("arguments[0].click();", element)

def select_ng_option(driver, dropdown_locator, option_text, timeout=10):
    """处理ng-select组件的选项选择"""
    # 点击下拉框
    wait_and_click(driver, dropdown_locator)
    # 等待下拉面板出现并定位目标选项
    option_locator = (By.XPATH, f"//ng-dropdown-panel//div[contains(text(), '{option_text}')]")
    wait_and_click(driver, option_locator, timeout)

# 初始化浏览器
driver = uc.Chrome()
driver.maximize_window()
driver.get('https://www.bcb.gov.br/estabilidadefinanceira/scrdata')

# 1. 选择Tipo do cliente -> PJ
tipo_cliente_dropdown = (By.XPATH, "//div[contains(text(), 'Tipo do cliente')]/following-sibling::ng-select")
select_ng_option(driver, tipo_cliente_dropdown, "PJ")

# 2. 处理CNAE选项循环添加
cnae_dropdown = (By.XPATH, "//div[contains(text(), 'CNAE')]/following-sibling::ng-select")

# 获取所有PJ相关的CNAE选项文本(这里假设PJ选项文本都包含" - PJ",可根据实际调整)
wait = WebDriverWait(driver, 10)
wait_and_click(driver, cnae_dropdown)
pj_options = wait.until(EC.presence_of_all_elements_located(
    (By.XPATH, "//ng-dropdown-panel//div[contains(text(), ' - PJ')]")
))
pj_option_texts = [opt.text for opt in pj_options]
# 先点击页面空白处关闭下拉面板
wait_and_click(driver, (By.TAG_NAME, "body"))

# 循环逐个添加
add_button_locator = (By.XPATH, "//button[contains(text(), 'Adicionar série')]")
for text in pj_option_texts:
    # 打开CNAE下拉框并选择选项
    select_ng_option(driver, cnae_dropdown, text)
    # 点击添加按钮
    wait_and_click(driver, add_button_locator)
    # 等待添加完成(可选,根据页面加载情况调整)
    WebDriverWait(driver, 5).until(EC.staleness_of(driver.find_element(*cnae_dropdown)))

# 操作完成后关闭浏览器
driver.quit()

代码说明

  • wait_and_click:封装了等待点击逻辑,处理元素被遮挡的情况,用JS兜底点击
  • select_ng_option:专门处理ng-select组件的选择,通过文本匹配选项,避免索引依赖
  • 循环部分:先获取所有PJ相关选项的文本,再逐个选择并添加,确保覆盖所有目标活动
  • 全程使用显式等待,彻底解决因页面加载延迟导致的元素找不到问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 17:02:05