用于Python的Selenium Webdriver遇到循环问题

时间:2014-09-18 21:25:49

标签: python selenium-webdriver

我对WebDriver for Python有一个非常奇怪的问题。基本上,我有一系列的行动,当它们独立运行时,可以完美地运作:

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"}

似乎循环试图循环第一个动作

driver.find_element_by_id("lbAdd").click()

没有继续其余的。还有其他人经历过这个吗?感谢

编辑:

这是整个事情的大部分内容。该域受登录保护,因此我无法包含base_url。除此之外,其他一切都在这里。我还将添加另一个观察:我尝试先包含循环,以包含我在下面粘贴的所有内容,包括打开浏览器的操作。发生的事情是该程序刚刚在空白页面上打开浏览器很多次。这就是导致我认为循环只是循环第一个动作的理论,而不是它们的整个块。我认为ti可能是一个简单的语法错误(在我想要循环的块周围有类似{}的东西,但是唉,也没有运气)

#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:

感谢德国人的解决方案。我猜想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)

1 个答案:

答案 0 :(得分:0)

以下是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()