下面我将详细介绍几种最常见的 Selenium 循环场景,并提供清晰的代码示例。

遍历一组元素并执行操作
这是最常见的场景,你需要获取页面上所有商品的价格,或者点击页面上的所有“同意”按钮。
核心思路:
- 使用
find_elements(注意是复数形式) 定位到所有目标元素,这会返回一个列表。 - 使用
for循环遍历这个列表。 - 在循环体内,对列表中的每一个元素(即单个 WebElement 对象)进行操作。
示例代码: 假设我们要访问一个商品列表页面,并打印出每个商品的名称。
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
# 1. 设置 WebDriver
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
# 2. 打开目标网页
# 这里使用一个模拟的商品列表页面作为示例
driver.get("https://www.scrapingcourse.com/ecommerce/product-page-1/")
try:
# 3. 定位所有商品名称的元素
# 使用 CSS Selector 定位所有 class 为 "woocommerce-loop-product__title" 的 <h3> 标签
product_names = driver.find_elements(By.CSS_SELECTOR, "h3.woocommerce-loop-product__title")
# 4. 遍历元素列表并打印文本
print("--- 开始遍历商品名称 ---")
for product in product_names:
# product 是一个 WebElement 对象
print(product.text)
print("--- 遍历完成 ---")
# 另一个例子:点击所有“添加到购物车”按钮
print("\n--- 开始点击“添加到购物车”按钮 ---")
add_to_cart_buttons = driver.find_elements(By.CSS_SELECTOR, "button.add_to_cart_button")
for button in add_to_cart_buttons:
# 使用 JavaScript 点击,可以避免一些元素被遮挡的问题
driver.execute_script("arguments[0].click();", button)
# 添加短暂延时,观察效果
time.sleep(0.5)
print("--- 点击完成 ---")
finally:
# 5. 关闭浏览器
driver.quit()
处理分页内容
当需要抓取多个页面的数据时,就需要使用循环来模拟点击“下一页”的操作。

核心思路:
- 创建一个
while循环。 - 在循环内,处理当前页面的数据(如场景一)。
- 尝试定位“下一页”按钮。
- 如果找到“下一页”按钮并且可点击,则点击它,并让程序稍作等待。
- 如果找不到“下一页”按钮(或者它被禁用),则说明已经到达最后一页,使用
break退出循环。
示例代码: 抓取一个博客所有文章的标题。
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("https://www.scrapingcourse.com/ecommerce/page/1/") # 假设这是第一页
# 使用显式等待,提高稳定性
wait = WebDriverWait(driver, 10)
all_article_titles = []
try:
while True:
print(f"\n--- 正在处理当前页面: {driver.current_url} ---")
# 1. 获取当前页面的所有文章标题
article_titles = driver.find_elements(By.CSS_SELECTOR, "h1.entry-title a")
for title in article_titles:
all_article_titles.append(title.text)
print(f" - 找到文章: {title.text}")
# 2. 尝试找到并点击“下一页”按钮
# 假设下一页按钮的 CSS 选择器是 ".next.page-numbers"
try:
# 显式等待“下一页”按钮出现并可点击
next_button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".next.page-numbers")))
next_button.click()
# 点击后等待新页面加载
# 可以等待URL变化或者某个标志性元素出现
time.sleep(2) # 简单的等待,实际项目中建议更智能的等待
except Exception:
# 如果找不到“下一页”按钮,或者它不可点击,则捕获异常并退出循环
print("\n--- 未找到“下一页”按钮,抓取完成。 ---")
break
finally:
# 3. 关闭浏览器
driver.quit()
# 4. 打印所有结果
print("\n--- 所有文章标题汇总 ---")in all_article_titles:
print(title)
在循环中进行条件判断和断言
在自动化测试中,你经常需要检查某个元素是否存在,或者其文本是否符合预期,并根据结果执行不同的操作。
核心思路:

- 使用
try...except块或if条件语句结合find_element(单数形式)。 find_element如果找不到元素,会抛出NoSuchElementException异常。- 你可以利用这个特性来判断元素是否存在。
示例代码: 检查一个登录页面上是否有“忘记密码?”的链接,如果有的话就点击它。
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("https://www.scrapingcourse.com/ecommerce/my-account/") # 假设这是一个登录页面
try:
# --- 场景1: 使用 try/except 判断元素是否存在 ---
print("--- 场景1: 使用 try/except ---")
try:
forgot_password_link = driver.find_element(By.LINK_TEXT, "Lost your password?")
print("找到了“忘记密码”链接,现在点击它。")
forgot_password_link.click()
except Exception as e:
print(f"没有找到“忘记密码”链接,错误信息: {e}")
time.sleep(2) # 等待页面跳转
# --- 场景2: 结合 if 判断和 assert 断言 ---
print("\n--- 场景2: 结合 if 判断和 assert 断言 ---")
# 假设点击后,页面上会出现一个标题 "Lost Password"
try:
page_title = driver.find_element(By.CSS_SELECTOR, "h1.uc-page-title").text
assert "Lost Password" in page_title
print("断言成功:页面标题包含 'Lost Password'。")
except AssertionError:
print("断言失败:页面标题不包含 'Lost Password'。")
except Exception as e:
print(f"发生错误,可能页面元素未找到: {e}")
finally:
driver.quit()
结合 range() 的固定次数循环
有时你需要执行一个固定次数的操作,比如反复刷新页面直到某个元素出现。
核心思路:
使用 for 循环结合 range() 函数。
示例代码: 每隔5秒刷新一次页面,尝试在3次内找到某个元素。
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("https://www.example.com") # 示例页面
found = False
max_attempts = 3
attempt = 0
for attempt in range(max_attempts):
attempt += 1
print(f"尝试第 {attempt} 次...")
try:
# 尝试找到某个元素(这里用一个不存在的元素做演示)
special_element = driver.find_element(By.ID, "non-existent-id")
print("成功找到元素!")
found = True
break # 找到后立即退出循环
except Exception:
print(f"第 {attempt} 次尝试失败,元素未找到。")
if attempt < max_attempts:
print("等待5秒后刷新页面...")
time.sleep(5)
driver.refresh()
if not found:
print(f"在 {max_attempts} 次尝试后仍未找到元素。")
driver.quit()
总结与最佳实践
-
find_elementsvsfind_element:find_elements(复数): 返回一个列表,如果元素不存在,返回空列表[]。主要用于循环遍历。find_element(单数): 返回一个单个元素,如果元素不存在,会抛出NoSuchElementException异常。主要用于定位单个特定元素。
-
等待机制:
- 强制等待 (
time.sleep()):简单粗暴,但不推荐,因为它会固定等待,不管元素是否已经加载好,会降低脚本效率。 - 隐式等待 (
driver.implicitly_wait(10)):全局设置,在find_element或find_elements期间,如果元素未找到,会等待最多指定的时间,简单易用,但对所有元素生效。 - 显式等待 (
WebDriverWait):强烈推荐,它只针对特定元素进行等待,直到某个条件(如元素可见、可点击)满足或超时,代码更健壮、更高效。
- 强制等待 (
-
代码健壮性:
- 始终将你的 Selenium 代码放在
try...except...finally块中,确保即使脚本出错,浏览器也能被正确关闭 (driver.quit())。 - 使用有意义的变量名,并添加注释,让代码易于理解和维护。
- 始终将你的 Selenium 代码放在
希望这些示例和解释能帮助你更好地在 Python 中使用 Selenium 进行循环操作!
