2016-08-19 100 views
0

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

解决此问题的方法是正确下划线和等待驱动程序。登录页面,我可以成功地闯过:

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() 

这一步我能成功地找到一个名为说,button_a,之后我点击这个元素后,页面生成一个新的按钮说,button_b,为此,我使用等待存在命令。

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可以解决这个问题吗?

对不起,我只是网络浏览器自动化中的总noob。

回答

0

其实你错了,你要找到元素,然后使用等待WebElement。你应该尝试使用通过定位器代替如下: -

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'))) 
0

看来,司机是保持老DOM和 参考不跟踪添加到DOM新元素,页面不是 在点击button_a后重新加载,但我刚刚获得经典Spin Wheel,其中客户端动态生成新内容。 其实硒检测到的页面重载,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 。