- 批量操作元素:在页面上有多个结构相同的元素(如商品列表、搜索结果、菜单项),需要对每个元素执行相同的操作(如点击、获取文本、验证信息)。
- 分页处理:当数据需要多页展示时,通过循环点击“下一页”按钮,直到最后一页。
- 重试机制:当某个操作可能因为网络延迟或元素未加载而失败时,通过循环进行重试,直到成功或达到最大重试次数。
- 数据驱动测试:从一个数据源(如列表、CSV文件、Excel表格)中循环读取数据,并为每组数据执行测试用例。
下面我们通过具体的代码示例来讲解最常见的几种循环用法。

for 循环:最常见的用法
for 循环用于遍历一个可迭代对象(如列表、元组、字典,或者 Selenium 中的元素列表)。
示例1:遍历并操作一组元素
假设我们要在一个电商网站上搜索 "手机",然后验证搜索结果列表中的每个商品名称是否包含 "手机"。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import time
# 1. 设置 WebDriver
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.maximize_window()
driver.implicitly_wait(10) # 隐式等待,全局有效
# 2. 打开目标网站
driver.get("https://www.example-ecommerce.com") # 这里用示例网站代替
try:
# 3. 模拟搜索 "手机"
search_box = driver.find_element(By.ID, "search-input")
search_box.send_keys("手机")
search_button = driver.find_element(By.CSS_SELECTOR, "button.search-btn")
search_button.click()
# 4. 等待搜索结果加载
time.sleep(2) # 为了演示,使用固定等待,实际项目中建议用显式等待
# 5. 找到所有商品名称的元素
# 假设每个商品名称的 class 都是 "product-title"
product_titles = driver.find_elements(By.CSS_SELECTOR, ".product-title")
print(f"找到 {len(product_titles)} 个商品。")
# 6. 使用 for 循环遍历每个商品元素
for index, title_element in enumerate(product_titles):
# 获取元素的文本内容
product_name = title_element.text
print(f"商品 {index + 1}: {product_name}")
# 验证商品名称是否包含 "手机"
assert "手机" in product_name, f"验证失败!商品 '{product_name}' 不包含 '手机'。"
print(f" -> 验证通过!")
print("\n所有商品验证成功!")
except Exception as e:
print(f"测试过程中发生错误: {e}")
finally:
# 7. 关闭浏览器
driver.quit()
代码解析:
driver.find_elements(...):注意是Elements(复数),它会返回一个包含所有匹配元素的列表,如果找不到任何元素,它会返回一个空列表[],而不是报错。for title_element in product_titles::这个循环会遍历product_titles列表中的每一个元素,在每次循环中,title_element代表当前正在处理的那个商品标题的WebElement对象。enumerate(product_titles):这是一个非常有用的函数,它可以在遍历列表的同时,获取每个元素的索引(从0开始)。index就是索引,title_element是元素本身。
while 循环:适用于条件判断和重试
while 循环在某个条件为 True 时会一直执行,非常适合用于处理分页或重试逻辑。

示例2:处理分页数据
假设我们要抓取一个网站所有页面的文章标题,直到没有“下一页”按钮为止。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import time
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.maximize_window()
driver.implicitly_wait(5)
driver.get("https://www.example-blog.com/articles") # 示例博客页面
all_article_titles = []
# 使用 while 循环处理分页
while True:
try:
# 1. 获取当前页面的所有文章标题
article_elements = driver.find_elements(By.CSS_SELECTOR, "article h2 a")
for article_element in article_elements:
all_article_titles.append(article_element.text)
print(f"抓取到文章: {article_element.text}")
# 2. 查找 "下一页" 按钮
next_button = driver.find_element(By.CSS_SELECTOR, "a.next-page") # 假设下一页按钮的 class 是 "next-page"
# 3. 判断 "下一页" 按钮是否可点击(即是否是最后一页)
# 一个常见的判断方法是检查按钮的 'disabled' 属性是否存在,或者其 'href' 是否为 '#'
if 'disabled' in next_button.get_attribute('class'):
print("已到达最后一页。")
break # 如果是最后一页,跳出循环
# 4. 点击 "下一页" 按钮
next_button.click()
time.sleep(2) # 等待页面加载
except Exception as e:
# 如果找不到 "下一页" 按钮(例如在最后一页时),或者发生其他错误,则退出循环
print(f"找不到 '下一页' 按钮或发生错误: {e}")
break
print(f"\n总共抓取到 {len(all_article_titles)} 篇文章。")
driver.quit()
代码解析:
while True::创建一个无限循环,我们需要在循环内部通过break语句来手动退出。try...except:在循环中处理异常非常重要,因为当到达最后一页时,“下一页”按钮可能不存在,find_element会抛出NoSuchElementException异常,except块会捕获这个异常并执行break来退出循环。- 条件判断:我们通过检查按钮的
class属性中是否包含disabled来判断它是否被禁用,这是一种常见的分页处理逻辑。
示例3:重试机制
当点击一个按钮可能因为元素未准备好而失败时,我们可以用 while 循环来重试。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import time
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("https://example.com/some-page")
max_retries = 3
retry_count = 0
# 使用 while 循环进行重试
while retry_count < max_retries:
try:
# 尝试查找并点击一个可能加载缓慢的按钮
submit_button = driver.find_element(By.ID, "submit-button")
submit_button.click()
print("按钮点击成功!")
break # 成功则跳出循环
except Exception as e:
retry_count += 1
print(f"点击失败,正在进行第 {retry_count} 次重试... 错误: {e}")
if retry_count >= max_retries:
print("已达到最大重试次数,测试失败。")
# 可以在这里添加失败后的处理逻辑,比如截图
driver.save_screenshot("failure.png")
else:
time.sleep(2) # 等待一段时间再重试
driver.quit()
for 循环结合 break 和 continue
break:立即终止整个循环。continue:立即终止当前这次循环,并跳到下一次循环的开始。
示例4:使用 break 和 continue
假设我们有一个商品列表,我们想找到第一个价格为 "¥999" 的商品并点击它,如果找到价格低于 "¥100" 的商品则跳过它。

# ... (driver 初始化和页面打开代码省略) ...
# 假设我们已经获取了所有商品价格的元素列表
price_elements = driver.find_elements(By.CSS_SELECTOR, ".product-price")
for price_element in price_elements:
price_text = price_element.text
# 使用 continue 跳过不符合条件的商品
if "¥100" in price_text: # 假设价格格式是 "¥99"
print(f"跳过低价商品: {price_text}")
continue # 跳过本次循环的剩余部分,进入下一个商品
# 使用 break 找到目标后立即结束循环
if "¥999" in price_text:
print(f"找到目标商品: {price_text},正在点击...")
# 找到这个商品对应的“购买”按钮并点击
# 假设按钮在价格元素的父级 div 下
buy_button = price_element.find_element(By.XPATH, "./../button")
buy_button.click()
print("点击成功!")
break # 点击成功后,不再检查其他商品,直接退出循环
print("循环结束。")
最佳实践与注意事项
-
find_elementsvsfind_element:- 当你需要操作一组元素时,使用
find_elements(复数),它返回一个列表。 - 当你需要操作一个特定元素时,使用
find_element(单数),如果找不到它会抛出NoSuchElementException异常。
- 当你需要操作一组元素时,使用
-
等待策略:
- 避免
time.sleep():虽然time.sleep()简单易用,但它会固定等待,无论元素是否已经准备好,这会大大拖慢脚本的执行速度。 - 优先使用隐式等待
driver.implicitly_wait(10):它会全局设置一个等待时间,在查找元素时,如果元素没找到,会等待最多指定的时间,但它在元素可点击、可交互等方面不够精确。 - 复杂场景使用显式等待
WebDriverWait:这是最推荐的方式,可以精确地等待某个条件(如元素可见、可点击、包含特定文本)满足后再执行操作。
显式等待示例:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 等待最多10秒,直到id为 "submit-button" 的元素变得可点击 submit_button = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.ID, "submit-button")) ) submit_button.click() - 避免
-
性能优化:
- 在循环内部应尽量避免重复的、耗时的操作,如果页面的页眉和页脚在每一页都一样,就不要在循环的每一次迭代中都去重新获取它们。
- 尽量将
find_element操作放在循环外部,只在循环内部操作已经找到的元素。
| 循环类型 | 适用场景 | 关键点 |
|---|---|---|
for 循环 |
遍历一组元素(列表、元组等),如商品列表、菜单项。 | 使用 find_elements 获取元素列表,enumerate 可同时获取索引。 |
while 循环 |
基于条件重复执行,如分页爬取、重试机制。 | 需要设置明确的退出条件(break),并用 try...except 处理异常。 |
break |
在循环中提前终止整个循环。 | 通常在找到目标元素或达到某个条件后使用。 |
continue |
在循环中跳过当前迭代,直接进入下一次。 | 通常在遇到不符合条件的元素时使用。 |
掌握好循环的使用,是编写高效、健壮的 Selenium 自动化脚本的关键一步,希望这些示例和解释能帮助你更好地理解!
