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
相关产品推荐
相关产品推荐

