我使用python 3.6和selenium 3.8.1,Chrome浏览器来模拟输入订单的用户。我们使用的应用程序具有特别令人沮丧的自动化实现 - 只要产品的过滤器正在加载,就会弹出加载模式,但它并不真正覆盖它下面的元素。此外,加载时间波动很大,但有一个上限。如果我不使用过多的睡眠声明,硒会在加载正确的对象之前开始疯狂点击或点击元素,但当然会点击加载模式。 (有趣的是,加载模式只会填充屏幕视图,因此硒还可以与折叠下方的项目进行交互。:P)
解决这个问题:
def kill_evil_loading_modal(self):
# i pause for a second to make sure the loader has a chance to pop
time.sleep(1)
# pulling locator type and from another file: ("id","locator_id")
loading_modal = ProductsLocators.loading_modal_selector
# call a function that returns true/false for object if exists
check_for_evil = self.is_element_exist(*loading_modal)
while check_for_evil == True:
check_for_evil = self.is_element_exist(*loading_modal)
这很棒!我有大量的邪恶时间.sleep(x)语句,以避免加载模式,我现在抓住它,等待它继续前进。
如果我只需处理那两三次,我会继续前进。可悲的是,这个加载模式在每次点击之后点击...所以这就是我的主脚本现在的样子:
new_quote02_obj.edit_quote_job(**data)
new_quote03_obj.kill_evil_loading_modal()
new_quote03_obj.click_product_dropdown()
new_quote03_obj.kill_evil_loading_modal()
new_quote03_obj.click_product_dropdown_link()
new_quote03_obj.kill_evil_loading_modal()
new_quote03_obj.select_category_dropdown(scenario_data['category_name'])
new_quote03_obj.kill_evil_loading_modal()
new_quote03_obj.select_market_dropdown(scenario_data['local_sales_market'])
new_quote03_obj.kill_evil_loading_modal()
new_quote03_obj.add_products_job(scenario_data['product_list_original'])
new_quote03_obj.kill_evil_loading_modal()
new_quote03_obj.click_done_btn()
new_quote03_obj.kill_evil_loading_modal()
new_quote03_obj.next_btn_page()
如何重构以保持DRY?
答案 0 :(得分:2)
如果你想等到模态消失并避免使用time.sleep()
,你可以试试ExplicitWait:
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait as wait
wait(driver, 10).until_not(EC.visibility_of_element_located(("id", "locator_id")))
或
wait(driver, 10).until(EC.invisibility_of_element_located(("id", "locator_id")))
这应该允许您等待最多10秒(如果需要,增加延迟),直到具有指定选择器("id", "locator_id"
)的元素变得不可见
如果每次点击后出现模态,您可以实现自己的点击方式,例如
def click_n_wait(by, value, timeout=10):
wait(driver, timeout).until(EC.element_to_be_clickable((by, value))).click()
wait(driver, timeout).until(EC.invisibility_of_element_located(("id", "locator_id")))
并将其用作
click_n_wait("id", "button_id")
答案 1 :(得分:0)
正如您在问题中提到的那样只要加载产品的过滤器就会弹出一个加载模式,而不管其下面的加载器封面元素,您可以简单地wait
表示您要与之交互的下一个目标元素。按照这种方法,你可以完全摆脱看起来像开销的函数kill_evil_loading_modal()
。作为kill_evil_loading_modal()
函数的替代,您必须根据需要调用WebDriverWait()方法和正确的expected_conditions,如下所示:
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
# other code
WebDriverWait(driver, 2).until(EC.element_to_be_clickable((By.XPATH, "xpath_of_element_A"))).click()
WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.XPATH, "xpath_of_element_B"))).click()
WebDriverWait(driver, 3).until(EC.element_to_be_clickable((By.XPATH, "xpath_of_element_C"))).click()