如何在Selenium Python中精准选择含指定文本的重复div元素
如何用Selenium Python定位军中朋友的卡片并点击写信按钮?
我来帮你解决这个问题,结合你提供的HTML结构和初始代码,我们可以优化实现并解决你的两个核心需求:完整遍历所有有效卡片、规范提取姓名,同时处理姓名不存在的情况。
1. 完整遍历卡片并处理姓名不存在的情况
你的初始代码主要问题是没有过滤不可见的重复卡片(由swiper滑块生成的swiper-slide-duplicate元素),也没有处理遍历完所有卡片仍未找到目标的场景。下面是优化后的代码:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.common.exceptions import NoSuchElementException, TimeoutException def select_soldier_and_write_letter(self, soldier_name): try: # 等待卡片区域加载完成,避免过早查找元素 WebDriverWait(self.driver, 10).until( EC.presence_of_element_located((By.CLASS_NAME, "cafe-card-box")) ) # 获取所有卡片元素 all_cafes = self.driver.find_elements(By.CLASS_NAME, "cafe-card-box") target_found = False for cafe in all_cafes: # 跳过不可见的重复卡片(swiper滑块会生成重复的不可见元素) if not cafe.is_displayed(): continue try: # 提取姓名并匹配 id_div = cafe.find_element(By.CLASS_NAME, "id") span_text = id_div.find_element(By.TAG_NAME, "span").text extracted_name = span_text.split('(')[0].strip() if extracted_name == soldier_name: print(f"✅ 找到目标朋友:{soldier_name}") # 定位并点击"위문편지"按钮 write_btn = cafe.find_element(By.LINK_TEXT, "위문편지") write_btn.click() target_found = True break else: print(f"🔍 当前卡片是{extracted_name},继续查找...") except NoSuchElementException: # 跳过结构异常的卡片(避免因页面结构问题中断遍历) print("⚠️ 当前卡片结构异常,跳过") continue if not target_found: print(f"❌ 未找到姓名为{soldier_name}的朋友,请确认姓名是否正确") except TimeoutException: print("❌ 卡片区域加载超时,请检查网络或页面状态")
代码核心优化点:
- 等待页面加载:用
WebDriverWait确保卡片区域完全加载后再开始遍历,避免元素未就绪的问题 - 过滤不可见元素:通过
is_displayed()跳过swiper生成的重复不可见卡片,避免重复处理或错误点击 - 异常处理:捕获
NoSuchElementException跳过结构异常的卡片,捕获TimeoutException处理加载超时 - 未找到处理:用
target_found标记,遍历结束后提示未找到的情况
2. 更规范的姓名提取方法
你之前用[0:3]截取的方式不够灵活,万一遇到姓名长度变化的情况就会失效。根据你提供的姓名格式(姓名 (服役时长)),推荐两种更可靠的方法:
方法1:字符串分割
利用括号分割文本,取括号前的部分并去除首尾空格:
extracted_name = span_text.split('(')[0].strip()
这种方法简单直接,完全适配你提到的格式。
方法2:正则表达式(更灵活)
如果姓名和括号之间可能有多个空格,或者格式有微小变化,正则表达式更稳健:
import re # 匹配括号前的所有字符,忽略括号前的空格 match_result = re.match(r'(.+?)\s*\(', span_text) if match_result: extracted_name = match_result.group(1).strip() else: # 处理格式异常的情况 extracted_name = span_text.strip()
额外注意事项
- 滑块滚动问题:如果你的朋友卡片较多,需要滚动滑块才能显示全部,你可以在遍历前或遍历中加入滑块滚动逻辑,比如执行JavaScript滚动
swiper-wrapper元素:swiper_wrapper = self.driver.find_element(By.CLASS_NAME, "swiper-wrapper") self.driver.execute_script("arguments[0].scrollLeft = arguments[0].scrollWidth", swiper_wrapper) - 避免重复点击:因为swiper会生成重复的卡片元素,必须过滤不可见元素,否则可能会点击到不可见的重复按钮,导致操作无效。
内容的提问来源于stack exchange,提问作者user13957678
相关产品推荐
相关产品推荐

