基于子元素信息修改父元素Class属性的Selenium页面自动化问题咨询
嘿,我来帮你搞定这个Selenium的问题!你遇到的相同ID按钮无法激活的情况,其实可以通过两种思路解决:要么直接模拟用户点击切换状态(更符合真实操作),要么手动修改DOM的class属性。另外我也会帮你把获取价格的逻辑整合进去。
方案一:直接点击按钮的父容器(推荐)
页面上的这些按钮应该是Bootstrap的btn-group-toggle组件,这类组件通常是点击外层的div.btn来切换选中状态,自动把class改成btn active,而不是直接点击input元素。你可以通过子元素的ID来定位对应的父div,然后点击它:
# 处理RCPE选项(Yes) rcpe_yes_div = driver.find_element_by_xpath('//div[contains(@class, "btn") and input[@id="quote_equine_owner_hasSubscribedRcpe_0"]]') rcpe_yes_div.click() # 处理RCPE选项(No) rcpe_no_div = driver.find_element_by_xpath('//div[contains(@class, "btn") and input[@id="quote_equine_owner_hasSubscribedRcpe_1"]]') rcpe_no_div.click() # 同理处理兽医费用订阅选项 sub_yes_div = driver.find_element_by_xpath('//div[contains(@class, "btn") and input[@id="quote_equine_owner_subscribeVeterinaryCharge_0"]]') sub_yes_div.click() sub_no_div = driver.find_element_by_xpath('//div[contains(@class, "btn") and input[@id="quote_equine_owner_subscribeVeterinaryCharge_1"]]') sub_no_div.click()
这种方法不需要手动修改DOM,完全模拟用户操作,更稳定,也不容易出问题。
方案二:手动修改父元素的Class属性
如果你确实需要修改class属性,可以通过子元素找到父div,然后用Selenium的execute_script来修改:
# 找到Yes选项的input元素 rcpe_yes_input = driver.find_element_by_id('quote_equine_owner_hasSubscribedRcpe_0') # 获取它的直接父div parent_div = rcpe_yes_input.find_element_by_xpath('..') # 执行JS修改class属性 driver.execute_script("arguments[0].className = 'btn active';", parent_div)
这个方法直接修改DOM,适合一些特殊场景,但不如模拟点击自然。
整合到你的循环逻辑,获取最终价格
现在把这些逻辑整合到你的循环里,遍历所有年份、价格、Yes/No选项,然后提取价格。假设价格元素有特定的class或ID(你需要根据实际页面调整定位),完整代码如下:
import time from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By import csv driver = webdriver.Chrome() # 初始化你的浏览器驱动 driver.get('https://equi.generali.fr/devis-en-ligne-proprietaire-d-un-equide') # 先处理Cookie按钮(用显式等待替代sleep,更可靠) WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.ID, 'popin_tc_privacy_button')) ).click() # 获取年份和价格选项(过滤空值) input_year = driver.find_element_by_id('quote_equine_owner_equineBirthYear') options_year = [ option.get_attribute("value") for option in input_year.find_elements_by_tag_name('option') if option.get_attribute("value") ] input_gear = driver.find_element_by_id('quote_equine_owner_equineValue') options_gear = [ option.get_attribute("value") for option in input_gear.find_elements_by_tag_name('option') if option.get_attribute("value") ] # 定义所有需要遍历的Yes/No选项组合 rcpe_options = [ ('yes', 'quote_equine_owner_hasSubscribedRcpe_0'), ('no', 'quote_equine_owner_hasSubscribedRcpe_1') ] sub_options = [ ('yes', 'quote_equine_owner_subscribeVeterinaryCharge_0'), ('no', 'quote_equine_owner_subscribeVeterinaryCharge_1') ] # 存储结果的列表 price_results = [] # 遍历所有组合 for year in options_year: input_year.send_keys(year) time.sleep(2) if int(year) > 2000: for price in options_gear: input_gear.send_keys(price) time.sleep(2) # 遍历RCPE的Yes/No for rcpe_text, rcpe_id in rcpe_options: # 点击对应的按钮容器 rcpe_div = driver.find_element_by_xpath(f'//div[contains(@class, "btn") and input[@id="{rcpe_id}"]]') rcpe_div.click() time.sleep(1) # 遍历兽医订阅的Yes/No for sub_text, sub_id in sub_options: sub_div = driver.find_element_by_xpath(f'//div[contains(@class, "btn") and input[@id="{sub_id}"]]') sub_div.click() time.sleep(2) # 获取最终价格(这里需要根据实际页面调整元素定位,示例用价格类名) try: final_price = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, '//span[contains(@class, "price-amount")]')) ).text # 存储结果 price_results.append({ 'year': year, 'horse_value': price, 'rcpe': rcpe_text, 'veterinary_sub': sub_text, 'final_price': final_price }) print(f"获取到价格:年份{year},马匹价值{price},RCPE{rcpe_text},兽医订阅{sub_text},价格{final_price}") except Exception as e: print(f"获取价格失败:{e}") # 把结果保存到CSV文件 with open('horse_insurance_prices.csv', 'w', newline='', encoding='utf-8') as f: writer = csv.DictWriter(f, fieldnames=['year', 'horse_value', 'rcpe', 'veterinary_sub', 'final_price']) writer.writeheader() writer.writerows(price_results) driver.quit()
注意事项
- 你需要根据页面实际的价格元素定位调整XPath,比如用浏览器开发者工具查看价格对应的HTML标签和属性。
- 推荐用
WebDriverWait显式等待替代固定的time.sleep,可以避免页面加载慢导致的元素找不到问题。 - 如果页面有动态刷新,可能需要在点击选项后等待价格元素更新完成再提取。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

