Selenium Python多页爬取问题:循环无法终止及数据获取异常
解决Selenium多页数据提取的循环终止与最后一页数据问题
问题根源
- 循环无法自动终止:到达最后一页时,"Next page"按钮仍存在但处于禁用状态,原代码依赖
element_to_be_clickable()的超时异常终止循环,但该条件会持续等待元素变为可点击状态,导致循环卡住;部分场景下禁用按钮不会触发超时异常,循环会无限执行。 - 最后一页数据需手动终止才能获取:循环卡住后,程序无法执行到后续的数据合并与导出步骤,只有手动终止程序时,已收集的数据才会被保留。
修复方案
核心调整点
- 直接检查下一页按钮的禁用状态(通过
disabled属性或类名),而非依赖点击异常 - 确保循环结束后合并所有数据,避免丢失已收集的内容
- 添加页面切换后的等待逻辑,确保新页面加载完成
修改后的完整代码
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 from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager import pandas as pd opts = webdriver.ChromeOptions() opts.headless = True driver = webdriver.Chrome(ChromeDriverManager().install()) base_url = "XYZ" driver.maximize_window() driver.get(base_url) driver.set_page_load_timeout(50) # 等待页面初始元素加载 WebDriverWait(driver, 50).until(EC.presence_of_element_located((By.ID, 'all-my-groups'))) # 输入筛选条件 driver.find_element(By.XPATH, '//*[@id="sim-issueListContent"]/div[1]/div/div/div[2]/div[1]/span/div/input').send_keys('No Stock') dfs = [] page_counter = 0 wait = WebDriverWait(driver, 30) while True: # 等待当前页数据元素可见 wait.until(EC.visibility_of_all_elements_located((By.XPATH, "//div[contains(@class, 'alias-wrapper sim-ellipsis sim-list--shortId')]"))) # 提取当前页数据 cards = driver.find_elements(By.XPATH, "//div[contains(@class, 'alias-wrapper sim-ellipsis sim-list--shortId')]") sims = [[card.text] for card in cards] dfs.append(pd.DataFrame(sims)) print(f"已收集第 {page_counter} 页数据") page_counter += 1 # 检查下一页按钮状态 try: next_btn = wait.until(EC.presence_of_element_located((By.XPATH, '//button[@aria-label="Next page"]'))) # 判断按钮是否禁用:优先检查disabled属性,若无效则检查span类名 if next_btn.get_attribute("disabled") is not None: print("已到达最后一页,终止循环") break # 若按钮依赖span类名判断禁用,替换为以下代码(根据实际禁用类调整) # span_element = next_btn.find_element(By.TAG_NAME, "span") # if "awsui_variant-disabled" in span_element.get_attribute("class"): # print("已到达最后一页,终止循环") # break # 点击下一页并等待页面切换 next_btn.click() wait.until(EC.staleness_of(cards[0])) # 等待当前页元素失效,确保新页面加载 except TimeoutException: print("未找到下一页按钮或超时,终止循环") break # 合并所有数据并输出/保存 final_df = pd.concat(dfs, ignore_index=True) print(f"所有数据收集完成,共 {len(final_df)} 条记录") # 可选:保存到本地文件 # final_df.to_csv("no_stock_data.csv", index=False) driver.quit()
关键修改说明
- 禁用状态判断:通过
get_attribute("disabled")直接检查按钮是否禁用,比等待点击异常更可靠;若页面用类名标识禁用状态,可切换为检查span元素的类名。 - 页面切换等待:使用
EC.staleness_of()等待当前页元素失效,确保新页面完全加载后再进行下一轮数据提取。 - 数据合并:循环结束后用
pd.concat()合并所有页面的DataFrame,确保数据能正常输出或保存,无需手动终止程序。 - 代码优化:统一创建
WebDriverWait实例,用列表推导式简化数据收集逻辑,改用driver.quit()一次性关闭驱动与窗口。
内容的提问来源于stack exchange,提问作者Siva
相关产品推荐
相关产品推荐

