如何加速Python嵌套循环执行?基于Selenium自动化场景
Selenium表格遍历提速优化方案
针对6行6列表格嵌套循环耗时30秒的问题,核心优化方向是减少Selenium与浏览器的实时交互次数,把重复的DOM查询改成内存数据处理,具体优化步骤如下:
优化要点
- 预提取所有单元格数据到本地:一次性把所有单元格的日期、系数信息提取并处理好,后续循环完全在内存中进行,避免每次循环都调用
find_element(这是耗时的核心原因) - 提前计算固定值:把
today、buffer_date这类不会变化的值放在循环外计算,避免重复运算 - 调整循环逻辑:先过滤掉不符合日期条件的单元格,再在有效范围内匹配系数,减少无效遍历
- 简化异常处理:减少嵌套的try-except,避免不必要的性能损耗
修改后的代码
def __parse_full_page(self, url: str, data: dict = {}) -> bool: try: WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(Locator.PLAN)).click() cells = WebDriverWait(self.driver, 10).until(EC.visibility_of_all_elements_located(Locator.CELLS_TABLE)) current_url = str(self.driver.current_url) id_ticket = current_url.split("&")[-2].split("=")[-1] button_planning = self.driver.find_element(*Locator.CONFIRM) ticket_data = tickets.get(id_ticket) max_rate = 0 if ticket_data != "Заявка не найдена": _, max_rate = ticket_data.split(':') max_rate = int(max_rate) coefficients = ["Бесплатно"] + [f'✕{i}' for i in range(1, max_rate + 1)] # 提前计算固定日期值,避免循环内重复计算 today = datetime.now() buffer_days = int(config["BOT"]["BUFFER"]) buffer_date = today + timedelta(days=buffer_days) # 预提取并处理所有单元格数据到本地列表 cell_data_list = [] for cell in cells: try: # 一次性提取当前单元格的所有需要的数据 date_text = cell.find_element(*Locator.DATE).text date_text_clean = date_text.split(',')[0].strip() date_object = datetime.strptime(date_text_clean, "%d %B").replace(year=today.year) coefficient_text = cell.find_element(*Locator.RATE).text.strip() # 保存单元格元素和处理后的数据 cell_data_list.append({ "cell": cell, "date_object": date_object, "coefficient_text": coefficient_text, "date_text": date_text }) except ValueError as ve: print(f"Ошибка при преобразовании даты: {ve}") continue except Exception as e: print(f"Ошибка при извлечении данных ячейки: {e}") continue # 先过滤符合日期条件的单元格 valid_cells = [item for item in cell_data_list if item["date_object"] > buffer_date] # 遍历系数,在有效单元格中查找匹配项 for coefficient in coefficients: for item in valid_cells: if item["coefficient_text"] == coefficient: try: button_hover = item["cell"].find_element(*Locator.CHOOSE_HOVER) self.action.move_to_element(button_hover).perform() item["cell"].find_element(*Locator.CHOOSE).click() self.action.move_to_element(button_planning).click().perform() new_id_el = self.driver.find_element(*Locator.ID).text new_id = new_id_el.strip() logger.debug("ЗАЯВКА ПРОШЛА") self.__pretty_log({"id_ticket": id_ticket, 'coefficient': coefficient, 'date': item["date_text"], "new_id": new_id}) return True except Exception as e: print(f"Ошибка при нажатии 'Выбрать': {e}") continue except Exception as e: print(f"Ошибка: {e}") return False
优化效果说明
- 原来的嵌套循环中,每个单元格要多次调用
find_element(日期、系数、按钮),现在只在预提取时调用一次,后续都是内存操作,能把耗时从30秒压缩到1-2秒以内 - 提前过滤无效日期的单元格,减少后续循环的遍历次数
- 固定值只计算一次,避免重复运算
内容的提问来源于stack exchange,提问作者Dourfyt
相关产品推荐
相关产品推荐

