如何用Selenium判断元素存在并实现条件分支操作?
问题:处理Selenium中XPath变化的条件分支逻辑
我是Python编程新手,这是我编写的第一个Python脚本。我正在开发一个通过XPath点击网页元素的机器人,希望在目标元素不存在或出现其他元素时返回原页面。
现有代码片段如下:
# Wait for the second web element to be clickable followbutton = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[3]/div/div[2]/div/header[1]/div/div[1]/aside[2]/div/div/div[1]/div[1]/div[2]/button")) ) followbutton.click()
但有时关注按钮的XPath略有不同,变为/html/body/div[3]/div/div[2]/div/header[1]/div/div[1]/aside[2]/div/div/div[1]/div[1]/div[2]/div/button而非原XPath/html/body/div[3]/div/div[2]/div/header[1]/div/div[1]/aside[2]/div/div/div[1]/div[1]/div[2]/button。
我该如何实现条件分支:若元素对应前者XPath则执行driver.back(),若对应后者则执行followbutton.click()?
以下是完整代码片段供参考:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import NoSuchElementException import time # Create a new instance of the Firefox driver driver = webdriver.Firefox() # Set the starting page number page_num = 32 while True: # Navigate to the URL with the current page number url = f"https://urlhere.com/page={page_num}" driver.get(url) time.sleep(20) try: # Wait for the first web element to be clickable user1 = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[3]/div/div[2]/div/main/div/div[1]/div/div")) ) user1.click() # Wait for 10 seconds time.sleep(10) # Wait for the second web element to be clickable followbutton = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[3]/div/div[2]/div/header[1]/div/div[1]/aside[2]/div/div/div[1]/div[1]/div[2]/button")) ) followbutton.click() time.sleep(3) driver.back() # Wait for 5 seconds time.sleep(5) # 2nd user user2 = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[3]/div/div[2]/div/main/div/div[2]/div/div")) ) user2.click() time.sleep(2) # 2nd users follow button followbutton2 = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[3]/div/div[2]/div/header[1]/div/div[1]/aside[2]/div/div/div[1]/div[1]/div[2]/button")) ) followbutton2.click() driver.back() except: # If any exception occurs, break out of the loop break # Increment the page number page_num += 1 # Close the browser window driver.quit()
解决方案
核心思路是分别检查两个XPath对应的元素是否存在,再根据结果执行对应逻辑。可以通过WebDriverWait结合异常捕获来实现,同时覆盖元素不存在的边界情况。
步骤1:导入必要的异常类
在原有导入基础上,添加TimeoutException:
from selenium.common.exceptions import NoSuchElementException, TimeoutException
步骤2:修改关注按钮的处理逻辑
将原来直接等待单个XPath的代码,替换为嵌套的try-except结构,分别处理两种XPath的情况:
处理第一个用户的关注按钮
# 替换原来的followbutton等待和点击逻辑 try: # 检查需要返回原页面的XPath元素是否存在 WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, "/html/body/div[3]/div/div[2]/div/header[1]/div/div[1]/aside[2]/div/div/div[1]/div[1]/div[2]/button")) ) driver.back() except TimeoutException: # 第一个元素不存在,检查需要点击的XPath元素 try: followbutton = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[3]/div/div[2]/div/header[1]/div/div[1]/aside[2]/div/div/div[1]/div[1]/div[2]/div/button")) ) followbutton.click() time.sleep(3) driver.back() except TimeoutException: # 两个元素都不存在,直接返回原页面 driver.back()
处理第二个用户的关注按钮
同样的逻辑复制到第二个用户的处理部分:
# 替换原来的followbutton2等待和点击逻辑 try: # 检查需要返回原页面的XPath元素是否存在 WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, "/html/body/div[3]/div/div[2]/div/header[1]/div/div[1]/aside[2]/div/div/div[1]/div[1]/div[2]/button")) ) driver.back() except TimeoutException: # 第一个元素不存在,检查需要点击的XPath元素 try: followbutton2 = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[3]/div/div[2]/div/header[1]/div/div[1]/aside[2]/div/div/div[1]/div[1]/div[2]/div/button")) ) followbutton2.click() driver.back() except TimeoutException: # 两个元素都不存在,直接返回原页面 driver.back()
完整修改后的代码
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import NoSuchElementException, TimeoutException import time # Create a new instance of the Firefox driver driver = webdriver.Firefox() # Set the starting page number page_num = 32 while True: # Navigate to the URL with the current page number url = f"https://urlhere.com/page={page_num}" driver.get(url) time.sleep(20) try: # Wait for the first web element to be clickable user1 = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[3]/div/div[2]/div/main/div/div[1]/div/div")) ) user1.click() # Wait for 10 seconds time.sleep(10) # 处理第一个用户的关注按钮逻辑 try: WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, "/html/body/div[3]/div/div[2]/div/header[1]/div/div[1]/aside[2]/div/div/div[1]/div[1]/div[2]/button")) ) driver.back() except TimeoutException: try: followbutton = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[3]/div/div[2]/div/header[1]/div/div[1]/aside[2]/div/div/div[1]/div[1]/div[2]/div/button")) ) followbutton.click() time.sleep(3) driver.back() except TimeoutException: driver.back() # Wait for 5 seconds time.sleep(5) # 2nd user user2 = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[3]/div/div[2]/div/main/div/div[2]/div/div")) ) user2.click() time.sleep(2) # 2nd users follow button # 处理第二个用户的关注按钮逻辑 try: WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, "/html/body/div[3]/div/div[2]/div/header[1]/div/div[1]/aside[2]/div/div/div[1]/div[1]/div[2]/button")) ) driver.back() except TimeoutException: try: followbutton2 = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[3]/div/div[2]/div/header[1]/div/div[1]/aside[2]/div/div/div[1]/div[1]/div[2]/div/button")) ) followbutton2.click() driver.back() except TimeoutException: driver.back() except Exception as e: # If any exception occurs, break out of the loop break # Increment the page number page_num += 1 # Close the browser window driver.quit()
补充说明
- 使用
presence_of_element_located而非element_to_be_clickable检查第一个XPath,因为我们只需要判断元素是否存在,不需要确保它可点击。 - 嵌套try-except结构可以覆盖三种情况:第一个元素存在、第二个元素存在、两个元素都不存在。
- 建议尽量避免使用绝对XPath(从/html开始的路径),页面结构稍有变化就会失效。可以改用相对XPath,比如根据按钮文本或class定位,例如
//button[text()='关注']或//div[contains(@class, 'follow-btn-wrap')]/button,稳定性会更高。
内容的提问来源于stack exchange,提问作者Drew Hansen
相关产品推荐
相关产品推荐

