我在使用 WebDriver for Python 时遇到了一个非常奇怪的问题。基本上,我有一个 Action block ,当它们单独运行时,它们可以完美地工作:
driver.find_element_by_id("lbAdd").click()
driver.find_element_by_id("lblAutoAssignAdvId").click()
driver.find_element_by_id("txtCampaignName").clear()
driver.find_element_by_id("txtCampaignName").send_keys("Campaign X")
Select(driver.find_element_by_id("ddlCampaignTypes")).select_by_visible_text("Type 1")
driver.find_element_by_id("btnCampaignSave").click()
但是当我尝试做不止一个时,即将它放入一个循环中:
x=1
while (x < 3):
driver.find_element_by_id("lbAdd").click()
driver.find_element_by_id("lblAutoAssignAdvId").click()
driver.find_element_by_id("txtCampaignName").clear()
driver.find_element_by_id("txtCampaignName").send_keys("Campaign X")
Select(driver.find_element_by_id("ddlCampaignTypes")).select_by_visible_text("Type 1")
driver.find_element_by_id("btnCampaignSave").click()
x=x+1
我一直收到这个错误:
Unable to locate element: {"method":"id","selector":"lblAutoAssignAdvId"}
看起来循环试图只循环第一个 Action
driver.find_element_by_id("lbAdd").click()
没有继续他们的其余部分。还有其他人经历过吗?谢谢
编辑:
这里是整个事情的大部分。该域受登录保护,因此我无法包含 base_url。除此之外,其他一切都在这里。我还要添加另一个观察结果:我之前尝试包含循环,以包含我在下面粘贴的所有内容,包括打开浏览器的操作。发生的事情是该程序多次在空白页面上打开浏览器。这就是让我得出这样一个理论的原因,即循环只是循环第一个 Action ,而不是整个 Action block 。我认为 ti 可能是一个简单的语法错误(我想循环的 block 周围有 {} 之类的东西,但是唉,也没有运气)
#Open Firefox
driver = webdriver.Firefox()
#Login in to Database
driver.get(base_url + "/Login.aspx?return=Default.aspx")
driver.find_element_by_id("txtUsername").clear()
driver.find_element_by_id("txtUsername").send_keys(username)
driver.find_element_by_id("txtPassword").clear()
driver.find_element_by_id("txtPassword").send_keys(password)
driver.find_element_by_id("btnLogin").click()
#Waaaaaaait for it
time.sleep(10)
#Select Campaign Table
Select(driver.find_element_by_id("ddlTables")).select_by_visible_text("Campaign")
driver.find_element_by_css_selector("option[value=\"Campaign\"]").click()
#Fill in Camapign Info Fields & Save
driver.find_element_by_id("lbAdd").click()
driver.find_element_by_id("lblAutoAssignAdvId").click()
driver.find_element_by_id("txtCampaignName").clear()
driver.find_element_by_id("txtCampaignName").send_keys("Campaign X")
Select(driver.find_element_by_id("ddlCampaignTypes")).select_by_visible_text("Type 1")
driver.find_element_by_id("btnCampaignSave").click()
编辑 2:
感谢 German 提供的解决方案。我猜 webdriver 在继续下一步之前需要一些周期性的中断来加载东西,因此循环失败。此代码有效:
for x in range(0,1000):
driver.find_element_by_id("lbAdd").click()
time.sleep(1)
driver.find_element_by_id("lblAutoAssignAdvId").click()
time.sleep(1)
driver.find_element_by_id("txtCampaignName").clear()
driver.find_element_by_id("txtCampaignName").send_keys("Campaign X")
Select(driver.find_element_by_id("ddlCampaignTypes")).select_by_visible_text("Type 1")
driver.find_element_by_id("btnCampaignSave").click()
time.sleep(2)
请您参考如下方法:
这是 German's 的替代方法答案(来自上面的评论)将大大减少等待时间:
定义这个等待元素并在元素可用时立即返回的方法:
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
def wait_for_element_by_id(self, element_id, timeout):
try:
return WebDriverWait(driver, timeout).until(EC.presence_of_element_located((By.ID, element_id)))
except TimeoutException:
return None
# or do something else here
然后替换
time.sleep(1)
driver.find_element_by_id("lblAutoAssignAdvId").click()
与
wait_for_element_by_id("lblAutoAssignAdvId", 1).click()
或者只是
WebDriverWait(driver, 1).until(EC.presence_of_element_located((By.ID, "lblAutoAssignAdvId")))
如果您不关心定义函数。
我发现等待条件而不是等待明确的时间通常是一种很好的做法,这样做将使您的自动化必须更快。您可能会遇到这样的情况,尽管您正在等待的 DOM 元素存在,但它可能尚未显示,并且尝试对其调用 click() 将引发 ElementNotVisibleException。在这种情况下,您可能希望在点击之前使用 expected_conditions.visibility_of()。
