Selenium爬取模态框数据:循环处理会话及分页爬取方案咨询
问题
需要爬取URL https://s7.goeshow.com/apa/annual/2023/session_search.cfm 中每个会话模态框内的数据——点击会话标题弹出模态框后提取内容。现有代码点击链接后崩溃,同时需要实现循环处理全部500个会话(页面每页仅显示50个)。
原代码:
import time from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait url = 'https://s7.goeshow.com/apa/annual/2023/session_search.cfm' options = Options() # options.add_argument('--headless') # options.add_argument('--disable-gpu') driver = webdriver.Chrome(chrome_options=options) driver.get(url) time.sleep(3) test = driver.find_elements(By.CSS_SELECTOR, '.session-title') for session in test: print(session) time.sleep(3) session.click() time.sleep(3) test2 = driver.find_elements(By.CSS_SELECTOR, '//.col-sm-12 col-md-12') driver.back()
解决方案
原代码核心问题
- 缺失依赖导入:使用
Options()但未从selenium.webdriver.chrome.options导入,直接运行会报错。 - 定位语法混用:
test2用了CSS_SELECTOR却写了XPath路径,正确的多类名CSS选择器应为.col-sm-12.col-md-12。 - 错误的弹窗关闭方式:用
driver.back()会刷新页面,导致之前获取的会话元素列表失效,应该点击模态框的关闭按钮。 - 未处理分页逻辑:没有自动翻页的代码,无法覆盖全部500个会话。
- 硬等待不稳定:
time.sleep无法保证元素就绪,容易出现元素未加载完成就执行操作的情况。
修正后的完整代码
import time from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC url = 'https://s7.goeshow.com/apa/annual/2023/session_search.cfm' options = Options() # 如需无头模式取消以下注释 # options.add_argument('--headless=new') # options.add_argument('--disable-gpu') driver = webdriver.Chrome(options=options) wait = WebDriverWait(driver, 10) try: driver.get(url) # 分页循环处理所有会话 while True: # 等待当前页会话标题加载完成 session_titles = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '.session-title'))) print(f"当前页加载 {len(session_titles)} 个会话") # 遍历当前页每个会话 for idx in range(len(session_titles)): # 重新定位元素,避免 stale element 错误 current_session = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, f'.session-title:nth-child({idx+1})'))) current_session.click() # 等待模态框内容加载并提取数据 modal_content = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.modal-body .col-sm-12.col-md-12'))) session_data = modal_content.text print(f"会话 {idx+1} 内容:\n{session_data}\n---") # 关闭模态框 close_btn = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.modal-header .close'))) close_btn.click() # 等待模态框完全关闭 wait.until(EC.invisibility_of_element_located((By.CSS_SELECTOR, '.modal.fade.in'))) # 尝试点击下一页 try: next_page_btn = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'li.next a'))) # 检查下一页按钮是否可用 if 'disabled' not in next_page_btn.get_attribute('class'): next_page_btn.click() # 等待页面刷新完成 wait.until(EC.staleness_of(session_titles[0])) else: print("已处理所有页面,爬取结束") break except: print("无更多页面,爬取结束") break finally: driver.quit()
关键优化说明
- 显式等待替代硬等待:用
WebDriverWait等待元素可见/可点击,避免因网络延迟导致的元素未就绪问题。 - 元素重定位:循环中重新定位会话元素,防止页面交互后出现
StaleElementReferenceException。 - 正确关闭模态框:点击模态框自带的关闭按钮,保持当前页面状态,确保分页遍历正常。
- 自动分页处理:通过检查下一页按钮的状态,自动翻页直到所有会话处理完成。
内容的提问来源于stack exchange,提问作者Sagar Jhamb
相关产品推荐
相关产品推荐

