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

Python中delete_loop函数无法循环200次的问题排查请求

问题:递归delete_loop函数仅执行一次就退出

我使用Python结合Selenium编写了自动化脚本,其中通过递归实现的delete_loop函数本应连续运行200次后再继续后续流程,但实际该函数仅执行一次就退出。以下是完整代码:

import time
from selenium import webdriver
from selenium.common.exceptions import ElementClickInterceptedException
from selenium.common.exceptions import ElementNotInteractableException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
import csv
from selenium.common.exceptions import TimeoutException


# Set up the Selenium driver
driver = webdriver.Chrome()

options = webdriver.ChromeOptions()
options.add_argument('--disable-notifications') # Disable notifications
driver = webdriver.Chrome(options=options)

# Wait for 2 minutes before starting
time.sleep(60)

driver.get("https://my.zonguru.com/#!/sales-spy")

def input_asins(driver):
    # Load the ASINs from the CSV file
    asins = []
    with open('asins.csv', 'r', encoding='utf-8-sig') as f:
        reader = csv.reader(f)
        for row in reader:
            asins.extend(row)

    # Input the ASINs
    asins_to_input = asins[:200]
    asins = asins[200:]
    asin_input = driver.find_element(By.CSS_SELECTOR, 'input.asins-counter__input')
    asin_input.clear()
    asin_input.send_keys(','.join(asins_to_input))

    # Remove the ASINs that have been inputted
    with open('asins.csv', 'w', newline='') as f:
        writer = csv.writer(f)
        writer.writerows([asins])

    # Select the 'AU' option
    country_select = driver.find_element(By.XPATH, '//*[@id="private-content"]/div/div/div/zg-product-tracker/div/div/div/div[2]/div/form/div[3]/div/select')
    try:
        country_select.click()
    except ElementClickInterceptedException:
        pass
    except ElementNotInteractableException:
        pass
    au_option = driver.find_element(By.CSS_SELECTOR, 'option[value="AU"]')
    try:
        au_option.click()
    except ElementClickInterceptedException:
        pass
    except ElementNotInteractableException:
        pass

    # Click the submit button
    submit_button = driver.find_element(By.CSS_SELECTOR, 'button.zg-btn-green')
    try:
        submit_button.click()
    except ElementClickInterceptedException:
        pass
    except ElementNotInteractableException:
        pass

def delete_loop(count):
    if count == 0:
        return
    # Click the dropdown
    dropdown_button = driver.find_element(By.CSS_SELECTOR, '.dropdown > .btn')
    try:
        dropdown_button.click()
    except ElementClickInterceptedException:
        pass
    except ElementNotInteractableException:
        pass

    # Click the delete
    delete_button = driver.find_element(By.CSS_SELECTOR, 'a.btn-delete')
    try:                
        delete_button.click()
    except ElementClickInterceptedException:
        pass
    except ElementNotInteractableException:
        pass

    # Click the ok
    ok_button = driver.find_element(By.CSS_SELECTOR, 'button#alertify-ok')
    try:
        ok_button.click()
    except ElementClickInterceptedException:
        pass
    except ElementNotInteractableException:
        pass
    
    # Call the function again with decremented count
    delete_loop(count - 1)

# Continuous loop
while True:
    try:
        # Load the ASINs
        input_asins(driver)

        time.sleep(60)

        # Click the download
        download_button = driver.find_element(By.CSS_SELECTOR, 'button.zg-btn-white')
        try:
            download_button.click()
            time.sleep(5) # Wait for 5 seconds to allow the file to download
        except ElementClickInterceptedException:
            pass
        except ElementNotInteractableException:
            pass

        delete_loop(200)

    except Exception as e:
        time.sleep(10)
        input_asins(driver)

     
# Close the Selenium driver
driver.quit()

问题原因分析

  • 元素定位未等待页面刷新:每次删除操作后页面会更新(比如移除一条记录、弹窗关闭),但代码直接用driver.find_element立即查找元素,未等待页面完成刷新,第二次递归时大概率找不到目标元素,触发未捕获的异常导致递归终止。
  • 异常捕获范围不足:delete_loop仅捕获了点击相关的两种异常,但查找元素时可能抛出NoSuchElementException,该异常未被处理会直接中断整个递归流程。
  • 无操作后等待机制:点击删除、确认按钮后,页面需要时间完成响应(如弹窗消失、列表重新渲染),直接递归调用下一次操作,元素还未准备就绪,导致操作失败并中断。

修复方案

1. 替换递归为循环(更稳定)

递归200次虽未达Python默认递归深度限制,但循环更适合这种重复执行的场景,避免递归调用栈的潜在问题。

2. 添加显式等待

用WebDriverWait替代直接查找元素,确保元素加载完成且可交互后再操作,避免页面未刷新导致的元素定位失败。

3. 完善异常捕获

捕获所有Selenium相关异常,避免单个操作失败导致整个流程中断。

修改后的delete_loop函数

from selenium.common.exceptions import NoSuchElementException

def delete_loop(count):
    wait = WebDriverWait(driver, 10)  # 设置10秒超时
    for _ in range(count):
        try:
            # 等待下拉按钮可点击并点击
            dropdown_button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.dropdown > .btn')))
            dropdown_button.click()
            
            # 等待删除按钮可点击并点击
            delete_button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'a.btn-delete')))
            delete_button.click()
            
            # 等待确认按钮可点击并点击
            ok_button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'button#alertify-ok')))
            ok_button.click()
            
            # 等待页面完成刷新(可选,根据实际页面响应调整)
            time.sleep(1)
        except (ElementClickInterceptedException, ElementNotInteractableException, NoSuchElementException, TimeoutException):
            # 遇到异常时跳过当前循环,继续下一次删除
            continue

额外优化建议

  • 替换input_asins中的driver.find_element为显式等待,避免固定time.sleep的不稳定;
  • 主循环中的time.sleep(60)也可替换为显式等待,等待页面加载完成后再执行后续操作;
  • 增加日志记录,方便排查每次操作的执行情况。

内容的提问来源于stack exchange,提问作者Brenduan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 10:53:12