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

Python Selenium循环遍历中显式等待随机报错问题求助

解决Selenium遍历股票列表时的随机超时&失效元素问题

嘿,我看你这个脚本在遍历SEC网站的股票列表时老是随机报错——一会儿超时、一会儿元素失效,虽然用了显式等待但还是没解决对吧?我来帮你拆解下问题,再给你重构后的稳定版本代码。

首先,先分析下你遇到的两个核心报错:

  • TimeoutException:你现在的代码是硬等2秒找弹窗,但这个弹窗不是每次都会出现,没找到就触发异常,进入异常分支后又重复执行搜索逻辑,反而增加了出错概率。
  • StaleElementReferenceException:这是Selenium里常见的坑——页面跳转或者局部刷新后,之前定位的元素对象就失效了,你之前的代码有时候复用了旧的元素引用,或者没等页面完全加载就操作,自然会触发这个错误。

接下来是具体的修复方案,我把代码重构了,同时解决这两个问题:

一、优化弹窗处理逻辑

不要强制等待弹窗,改成只在弹窗存在时才点击,不存在就直接跳过:

try:
    pop_up = WebDriverWait(driver, 2).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="acsMainInvite"]/div/a[1]')))
    pop_up.click()
except TimeoutException:
    pass  # 没弹窗就不用管

二、避免元素失效的核心技巧

元素失效的本质是页面刷新后旧的元素引用作废,所以要做到:

  1. 每次操作前重新定位元素,不要复用之前存的WebElement对象
  2. 页面跳转后必须等待新页面加载完成,比如等待关键元素出现或者旧元素失效

三、重构后的完整稳定代码

我把重复的逻辑封装成了函数,同时加了很多稳定性增强的细节:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException

list_adjusted = ['MSFT', 'AAPL', 'GOOGL', 'GOOG', 'AMZN', 'TSLA', 'FB', 'BRK-B', 'BRK-A', 'NVDA', 'TSM', 'JPM', 'V', 'BABA', 'JNJ', 'UNH', 'WMT', 'HD', 'BAC', 'PG', 'MA', 'ASML', 'DIS', 'ADBE', 'NFLX', 'CRM', 'TM', 'PYPL', 'XOM', 'NKE', 'ORCL', 'TMO', 'PFE', 'KO', 'LLY', 'CSCO', 'CMCSA', 'ACN', 'ABT', 'INTC', 'MRK', 'PEP', 'VZ', 'DHR', 'CVX', 'AVGO', 'COST', 'WFC', 'NVS', 'ABBV', 'SE', 'NVO', 'SHOP', 'AZN', 'MCD', 'MS', 'T', 'UPS', 'RDS-A', 'VTI', 'SAP', 'TXN', 'RDS-B', 'INTU', 'NEE', 'LOW', 'LIN', 'BX', 'MDT', 'HON', 'PTR', 'UNP', 'SCHW', 'QCOM', 'RY', 'PM', 'AMD', 'MRNA', 'TMUS', 'SONY', 'BLK', 'C', 'NOW', 'BBL', 'UL', 'GS', 'BHP', 'RTX', 'TTE', 'TD', 'HDB', 'AXP', 'BMY', 'ISRG', 'AMT', 'TGT', 'SBUX', 'CHTR', 'SNY', 'JD', 'SQ', 'HSBC', 'BA', 'AMAT', 'AMGN', 'CVS', 'DEO', 'TEAM', 'GE', 'LFC', 'EL', 'SNAP', 'SPGI', 'IBM', 'CAT', 'ABNB', 'PDD', 'PLD', 'SNOW', 'DE', 'BUD', 'ANTM', 'GSK', 'MMM', 'RIO', 'ZTS', 'SYK', 'BKNG', 'COP', 'BP', 'INFY', 'BAM', 'ADP', 'ADI', 'CNI', 'LMT', 'USB', 'PNC', 'ENB', 'EQNR', 'MDLZ', 'UBER', 'MMC', 'TFC', 'CB', 'SHW', 'DELL', 'HCA', 'MO', 'GILD', 'ZM', 'CSX', 'GM', 'BTI', 'BNS', 'TJX', 'LRCX', 'MU', 'SNP', 'CME', 'DUK', 'MELI', 'CCI', 'ICE', 'IBN', 'MUFG', 'MCO', 'EW', 'EQIX', 'CI', 'WBK', 'WDAY', 'AON', 'ITW', 'NSC', 'BMO', 'BNTX', 'ADSK', 'BDX', 'F']

stocks_with_sec_fillings = []
yday = "2024-05-20"  # 替换成你实际的昨天日期格式,要和SEC页面的日期格式一致

def get_latest_filing_date(driver, ticker):
    # 重新访问SEC主页,避免页面状态混乱
    driver.get('https://www.sec.gov/')
    
    # 处理弹窗:只在出现时点击
    try:
        pop_up = WebDriverWait(driver, 2).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="acsMainInvite"]/div/a[1]')))
        pop_up.click()
    except TimeoutException:
        pass
    
    # 定位搜索框,先清空再输入
    search_box = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, '//*[@id="global-search-box"]')))
    search_box.clear()
    search_box.send_keys(ticker)
    
    # 点击搜索结果第一条
    try:
        search_result = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="global-search-form"]/fieldset/div/div/div/table/tbody/tr/td[1]')))
        search_result.click()
    except TimeoutException:
        print(f"⚠️ 搜索{ticker}时未找到有效结果")
        return None
    
    # 等待页面加载完成:等待filings表格出现
    WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'filingsTable')))
    
    # 尝试点击"查看所有申报"按钮,点击后等待表格刷新
    try:
        view_all_btn = WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.ID, 'btnViewAllFilings')))
        view_all_btn.click()
        # 等待旧表格失效,再等待新表格加载完成
        WebDriverWait(driver, 10).until(EC.staleness_of(driver.find_element(By.ID, 'filingsTable')))
        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'filingsTable')))
    except TimeoutException:
        # 没有这个按钮就直接取现有表格数据
        pass
    
    # 获取最新申报日期
    try:
        date_element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, '//*[@id="filingsTable"]/tbody/tr[1]/td[3]')))
        return date_element.text
    except TimeoutException:
        print(f"⚠️ 无法获取{ticker}的最新申报日期")
        return None

# 初始化驱动,添加隐式等待作为兜底
driver = webdriver.Chrome("D:/chromedriver/chromedriver.exe")
driver.implicitly_wait(3)  # 全局等待3秒,处理短暂的加载延迟

# 遍历所有股票代码
for idx, ticker in enumerate(list_adjusted, 1):
    print(f"正在处理第{idx}只股票:{ticker}")
    filing_date = get_latest_filing_date(driver, ticker)
    if filing_date:
        print(f"✅ {ticker} 最新申报日期:{filing_date}")
        if filing_date == yday:
            stocks_with_sec_fillings.append([ticker, filing_date])

# 关闭驱动
driver.quit()

print("\n📌 符合条件的股票:")
for item in stocks_with_sec_fillings:
    print(item)

四、额外的稳定性小贴士

  1. 添加隐式等待:作为显式等待的兜底,处理一些短暂的页面加载延迟
  2. 每次输入前清空搜索框:避免之前的输入残留导致搜索结果错误
  3. 页面跳转后等待元素状态变化:比如点击"查看所有申报"后,等待旧表格失效再等待新表格出现,确保页面完全刷新
  4. 增加日志打印:方便定位哪只股票出了问题,后续可以针对性处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 21:57:40