如何实现Selenium同时点击同class元素以提升操作效率?
优化Selenium批量点击元素的速度问题
现有一段Selenium代码,逻辑是先点击页面上可能存在的加载类按钮,再点击所有class包含group-head的元素来展开折叠框。当前带time.sleep(0.1)时操作耗时约90秒,移除sleep后耗时降到65秒,但会随机出现部分元素被忽略的情况。需求是找到能高效批量点击同class元素、加快进程的方法。
原代码如下:
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.webdriver.firefox.options import Options import time my_user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36' options = Options() options.set_preference("general.useragent.override", my_user_agent) options.page_load_strategy = 'eager' options.add_argument('--headless') driver = webdriver.Firefox(options=options) driver.get("https://int.soccerway.com/matches/2022/07/23/") try: WebDriverWait(driver, 3).until(EC.presence_of_element_located((By.XPATH, "//a[contains(@class,'tbl-read-more-btn')]"))) driver.find_element(by=By.XPATH, value="//a[contains(@class,'tbl-read-more-btn')]").click() time.sleep(0.1) except: pass WebDriverWait(driver, 3).until(EC.presence_of_element_located((By.XPATH, "//tr[contains(@class,'group-head')]"))) for btn in driver.find_elements(by=By.XPATH, value="//tr[contains(@class,'group-head')]"): btn.click() time.sleep(0.1)
待点击按钮示例

点击后展开效果

可行优化方案
1. 用JavaScript批量点击(最快解决方式)
直接通过浏览器执行JS代码,一次性选中所有目标元素并触发点击,完全避免Selenium循环点击的开销和等待问题,同时可以过滤已展开的元素减少无效操作:
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.webdriver.firefox.options import Options my_user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36' options = Options() options.set_preference("general.useragent.override", my_user_agent) options.page_load_strategy = 'eager' options.add_argument('--headless') driver = webdriver.Firefox(options=options) driver.get("https://int.soccerway.com/matches/2022/07/23/") # 处理加载更多按钮:确保元素可点击再操作,用显式等待替代sleep try: load_more_btn = WebDriverWait(driver, 3).until( EC.element_to_be_clickable((By.XPATH, "//a[contains(@class,'tbl-read-more-btn')]")) ) load_more_btn.click() # 等待页面加载完成,直到按钮状态变化 WebDriverWait(driver, 2).until(EC.staleness_of(load_more_btn)) except: pass # 等待所有目标元素加载完成,再执行JS批量点击 WebDriverWait(driver, 3).until( EC.presence_of_all_elements_located((By.XPATH, "//tr[contains(@class,'group-head')]")) ) driver.execute_script(""" // 只点击未展开的元素,避免重复操作 document.querySelectorAll('tr.group-head:not(.expanded)').forEach(el => el.click()); """)
2. 优化显式等待,避免无效操作
- 把
presence_of_element_located替换为element_to_be_clickable,确保元素真正可交互再点击,避免因元素未就绪导致的漏点。 - 循环点击时,每次重新定位元素(因为点击后页面DOM可能更新,旧元素引用会失效),或者用
presence_of_all_elements_located确保所有元素都已加载。
3. 过滤已展开元素减少操作量
从示例效果看,折叠框展开后会添加expanded类,因此可以只定位未展开的元素,减少不必要的点击:
# 等待所有未展开的目标元素加载完成 WebDriverWait(driver, 3).until( EC.presence_of_all_elements_located((By.XPATH, "//tr[contains(@class,'group-head') and not(contains(@class,'expanded'))]")) ) # 循环点击未展开的元素,每次确保元素可点击 for btn in driver.find_elements(by=By.XPATH, value="//tr[contains(@class,'group-head') and not(contains(@class,'expanded'))]"): WebDriverWait(driver, 1).until(EC.element_to_be_clickable(btn)).click()
内容的提问来源于stack exchange,提问作者Digital Farmer
相关产品推荐
相关产品推荐

