杰瑞科技汇

selenium 循环 python

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

selenium 循环 python-图1
(图片来源网络,侵删)

遍历一组元素并执行操作

这是最常见的场景,你需要获取页面上所有商品的价格,或者点击页面上的所有“同意”按钮。

核心思路:

  1. 使用 find_elements (注意是复数形式) 定位到所有目标元素,这会返回一个列表。
  2. 使用 for 循环遍历这个列表。
  3. 在循环体内,对列表中的每一个元素(即单个 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()

处理分页内容

当需要抓取多个页面的数据时,就需要使用循环来模拟点击“下一页”的操作。

selenium 循环 python-图2
(图片来源网络,侵删)

核心思路:

  1. 创建一个 while 循环。
  2. 在循环内,处理当前页面的数据(如场景一)。
  3. 尝试定位“下一页”按钮。
  4. 如果找到“下一页”按钮并且可点击,则点击它,并让程序稍作等待。
  5. 如果找不到“下一页”按钮(或者它被禁用),则说明已经到达最后一页,使用 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)

在循环中进行条件判断和断言

在自动化测试中,你经常需要检查某个元素是否存在,或者其文本是否符合预期,并根据结果执行不同的操作。

核心思路:

selenium 循环 python-图3
(图片来源网络,侵删)
  1. 使用 try...except 块或 if 条件语句结合 find_element (单数形式)。
  2. find_element 如果找不到元素,会抛出 NoSuchElementException 异常。
  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.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()

总结与最佳实践

  1. find_elements vs find_element

    • find_elements (复数): 返回一个列表,如果元素不存在,返回空列表 []主要用于循环遍历。
    • find_element (单数): 返回一个单个元素,如果元素不存在,会抛出 NoSuchElementException 异常。主要用于定位单个特定元素。
  2. 等待机制

    • 强制等待 (time.sleep()):简单粗暴,但不推荐,因为它会固定等待,不管元素是否已经加载好,会降低脚本效率。
    • 隐式等待 (driver.implicitly_wait(10)):全局设置,在 find_elementfind_elements 期间,如果元素未找到,会等待最多指定的时间,简单易用,但对所有元素生效。
    • 显式等待 (WebDriverWait)强烈推荐,它只针对特定元素进行等待,直到某个条件(如元素可见、可点击)满足或超时,代码更健壮、更高效。
  3. 代码健壮性

    • 始终将你的 Selenium 代码放在 try...except...finally 块中,确保即使脚本出错,浏览器也能被正确关闭 (driver.quit())。
    • 使用有意义的变量名,并添加注释,让代码易于理解和维护。

希望这些示例和解释能帮助你更好地在 Python 中使用 Selenium 进行循环操作!

分享:
扫描分享到社交APP
上一篇
下一篇