使用Selenium

时间:2016-08-19 00:53:02

标签: python selenium selenium-webdriver selenium-chromedriver

我正在使用Selenium和Chrome驱动程序,但我无法通过ID找到元素。但是,此元素在浏览器的Web检查器中可见。我认为这是因为元素是动态生成的(我一直在浏览器URL栏中看到相同的URL,但内容会动态变化。

解决问题的方法是正确地解决驱动程序等待问题。第一页是我可以成功通过的登录页面:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
delay = 5

username = driver.find_element_by_name('Username')
password = driver.find_element_by_name('Password')
username.send_keys('my_username')
password.send_keys('my_password')
login = driver.find_element_by_id('login_button')
login.click()

在这一步之后,我可以成功找到名为say,button_a的元素,点击此按钮后,页面会生成一个新按钮,例如button_b,我使用wait for presence命令。

button_a = driver.find_element_by_id('button_a')
button_a.click()
WebDriverWait(driver, delay).until(
    EC.presence_of_element_located(
        driver.find_element_by_id('button_b')))

然而,这引发了经典的例外:

selenium.common.exceptions.NoSuchElementException: Message: no such element:     Unable to locate element: {"method":"id","selector":"button_b"}

似乎驱动程序保留了对旧DOM的引用,并且没有跟踪添加到DOM的新元素,单击button_a后页面没有重新加载但是我只获得了经典的Spin Wheel客户端正在动态生成新内容。此时我可以通过右键单击浏览器然后检查来清楚地看到button_b id存在。

用Selenium可以解决这个问题吗?

对不起,我只是网页浏览器自动化中的一个菜鸟。

2 个答案:

答案 0 :(得分:0)

实际上你出错了,你将找到元素然后使用等待WebElement。你应该尝试使用By locator,如下所示: -

button_a = driver.find_element_by_id('button_a')
button_a.click()
button_b = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.ID, 'button_b')))

答案 1 :(得分:0)

  

似乎驱动程序正在保留对旧DOM的引用   不跟踪添加到DOM的新元素,页面不是   单击button_a后重新加载,但我得到了经典的旋转   客户端动态生成新内容的轮子。   实际上,Selenium会检测页面重新加载,AJAX调用,Javascript执行等对DOM所做的任何更改。   所以,要对此进行测试,如果您让我们说出您的button_a并尝试以下内容:

buttonA = driver.find_element_by_id("button_a")
//Ajax call here
buttonA.click()

您将收到StaleElementReferenceException错误(元素不再附加到DOM),这意味着Selenium对该元素所做的任何绑定都将丢失。

现在,为了克服你的问题,使用你的例子,你可以使用:

//get the first element, button_a and click it
//going by your example this means you have only one element containing `button`
//in the `id`
driver.find_element_by_xpath(".//*[contains(@id,'button')]").click()
//now, as you say, you will have 2 elements containing `button` in the `id`
//so get all the elements and click on the last one
buttonB = driver.find_elements_by_xpath(".//*[contains(@id,'button')]")
buttonB[len(buttonB)-1].click()

作为一个注释,我为任何语法错误道歉,如果有的话,因为我不是pythonist。