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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 14:37:53