Selenium+Python脚本逐行正常但批量运行异常的问题排查与修复
Hey there, let's break down why your Baidu Pan automation script is misbehaving and fix it step by step.
异常原因分析
1. 总运行耗时远低于预期
Your script uses try-except blocks with a bare pass statement — this means if any step fails (like elements not loading in time, wrong locators, or unexpected page state changes), the code immediately skips all subsequent steps in that try block, including the time.sleep(5) calls. For example, if the login page hasn't fully loaded when you try to interact with elements, or if the file can't be located right after login, the code jumps to except and skips the sleeps, leading to a much shorter total runtime than expected.
2. test2文件未被删除
There are a few key reasons for this:
- The first
tryblock might have hit an error (e.g., couldn't find test1, or the right-click menu'sli[21]index is no longer valid due to Baidu Pan UI updates), but since you're swallowing all exceptions withpass, you get no feedback about the failure. This leaves the page in an unexpected state, making it impossible to locate test2. - Using a fixed index
li[21]for the delete option is fragile — Baidu Pan's UI can change, so the position of the "Delete" option might shift. - After deleting test1, the page needs time to refresh, but your code immediately tries to find test2 without waiting, leading to a failed element lookup.
修复方案
Here's the revised script with fixes that address all these issues:
import time from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.common.exceptions import NoSuchElementException, TimeoutException # Initialize driver and wait object driver = webdriver.Chrome() driver.maximize_window() wait = WebDriverWait(driver, 15) # 15-second timeout for element waits try: # Navigate to Baidu Pan target = "https://pan.baidu.com/" driver.get(target) # Login credentials (replace with your actual info) name = 'your_username' passwd = 'your_password' # Wait for login tab to be clickable, then click login_tab = wait.until(EC.element_to_be_clickable((By.XPATH, '//div[@class="account-title"]/a'))) login_tab.click() # Enter username and password username_input = wait.until(EC.visibility_of_element_located((By.ID, 'TANGRAM__PSP_4__userName'))) username_input.send_keys(name) password_input = wait.until(EC.visibility_of_element_located((By.ID, 'TANGRAM__PSP_4__password'))) password_input.send_keys(passwd) # Click login button login_btn = wait.until(EC.element_to_be_clickable((By.ID, 'TANGRAM__PSP_4__submit'))) login_btn.click() # Wait for file list to load after login wait.until(EC.presence_of_element_located((By.XPATH, '//a[@title="test1"]'))) # Reusable function to delete a file by its title def delete_file(file_title): try: # Locate the file element file_path = wait.until(EC.visibility_of_element_located((By.XPATH, f'//a[@title="{file_title}"]'))) # Hover to trigger context menu ActionChains(driver).move_to_element(file_path).perform() # Right-click to open context menu ActionChains(driver).context_click(file_path).perform() # Locate delete option by text (resilient to UI changes) delete_option = wait.until(EC.element_to_be_clickable((By.XPATH, '//li[contains(text(), "删除")]'))) delete_option.click() # Confirm deletion confirm_btn = wait.until(EC.element_to_be_clickable((By.XPATH, '//span[contains(text(), "确定")]/parent::span/parent::button'))) confirm_btn.click() # Wait for file to disappear from list (ensure deletion is complete) wait.until(EC.invisibility_of_element_located((By.XPATH, f'//a[@title="{file_title}"]'))) print(f"Successfully deleted {file_title}") except (NoSuchElementException, TimeoutException) as e: print(f"Failed to delete {file_title}: {str(e)}") # Execute deletion for both files delete_file("test1") delete_file("test2") finally: # Ensure browser closes even if errors occur driver.quit()
Key Fixes Explained:
- Explicit Waits Over
time.sleep: UsingWebDriverWaitwithexpected_conditionsensures we only interact with elements when they're ready, eliminating race conditions from page loading delays. This makes the script more reliable and avoids unnecessary waits. - Specific Exception Handling: We now catch only relevant exceptions and print error messages, so you can see exactly where things go wrong instead of silent failures.
- Dynamic Context Menu Locator: Instead of a fixed index, we locate the delete option by its text (
contains(text(), "删除")), which is far more resilient to UI updates. - Reusable Delete Function: Wrapping the deletion logic in a function reduces code duplication and keeps the script clean.
- Wait for File Disappearance: After deleting a file, we wait until it's no longer visible, ensuring the operation is complete before moving to the next file.
finallyBlock: Guarantees the browser is closed even if an error occurs, preventing leftover driver instances.
内容的提问来源于stack exchange,提问作者showkey

