Selenium找到后来通过javascript加载的元素

时间:2018-02-14 02:56:53

标签: javascript python html selenium

所以我试图使用selenium来自动完成某些表单,但是我遇到了一个问题。我正在使用的其中一种表单不是由HTML直接加载,而是在页面正常加载后使用JavaScript加载。无论出于何种原因,selenium在javascript中加载后无法看到页面的更新源。例如,如果我运行以下代码。

browser = webdriver.Firefox()
browser.get('https://examplepage.com')

WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.ID, “13jres”))).send_keys(“email@email.com”)

什么都没发生,它超时了。在做了一些测试后,我注意到如果我在python中打印源代码,使用以下代码

browser = webdriver.Firefox()
browser.get('https://examplepage.com')
time.sleep(20)
print browser.page_source

然后源代码不同于我可以在selenium firefox实例中手动查看的源代码。所以下面这一行,我试图输入的内容,根据selenium源输出不存在,即使它显然在那里检查firefox中的元素或在Firefox实例中查看已加载的内容使用硒。

<input label=“Email” type="text" name="13jres" id="13jres" class="text-field”>(shortened to make it more readable)

通过阅读一些文档,我在引用page_source命令时发现了这一点,我想这解释了源代码的不同之处,但我仍然不清楚如何在页面上找到这些元素来缓解我的问题。我在selenium(safari,chrome等)中尝试过其他浏览器,但除此之外,我不确定我需要做什么。

“如果页面在加载后已被修改(例如,通过Javascript),则无法保证返回的文本是已修改页面的文本。请参阅用于确定返回文本是否反映网页当前状态或Web服务器最后发送的文本的特定驱动程序的文档。“

3 个答案:

答案 0 :(得分:2)

正如您所提到的Nothing happens and it times out.,这实际上意味着它可以是以下任何一种情况:

  • <input>代码:根据您提供的 缩短的HTML

    <input label=“Email” type="text" name="13jres" id="13jres" class="text-field”>(shortened to make it more readable)
    

    由于缩短了标记,我们无法理解<input>标记是否包含与之关联的onClick()事件。

    接下来你正试图:

    WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.ID, “13jres”))).send_keys(“email@email.com”)
    

    我们是否在右侧 webelement 上调用send_keys()仍未确定。

  • Locator Strategy:根据您的代码试用版,您尝​​试使用基于id定位器策略。但id属性设置为值 13jres 对我来说看起来很动态。因此,您可以更精细地调整更有效的Locator Strategy,如下所示:

    WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, “input.text-field[id$='jres']”))).send_keys(“email@email.com”)
    
  • 您可以在Official locator strategies for the webdriver

  • 中找到有关定位策略的详细讨论

答案 1 :(得分:1)

基于来自page_source的源代码使用selenium进行自动化可能是不好的做法,因为有两种主要情况,并且它们经常发生,其中实时页面背后的代码与初始网页源页面不同:< / p>

1。

page_source显示源页面,但源页面虽然实际上是DOM的原始种子页面,DOM可以更改,但JS代码会动态地更改它。 在这种情况下,est实践将是:

browser.get("url")
sleep(experimental) # usually get will finish only after the page is loaded but sometimes there is some JS woo running after on load time

try:
    element= WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID, 'your_id_of_interest')))
    print "element is ready do the thing!"
except TimeoutException:
    print "Somethings wrong!"   

2。

page_source未显示shadow DOMS如果您在shadow DOMS中看到该元素,则page_sourcebrowser或{{ 1}} JavaScript中的对象需要先扩展shadow-DOM

document

如果您在影子根中有影子根以查看更多详细信息,则会出现问题,请参阅此答案:Accessing Shadow DOM tree with Selenium

如果您想了解如何获取动态内容的源代码,您还可以看到我给出的答案:https://stackoverflow.com/a/48782708/1577343

答案 2 :(得分:0)

尝试等待页面完全加载然后执行操作。我不是在python中使用,但在javascriptexecutor中有一个选项

bool wait = new WebDriverWait(driver, TimeSpan.FromSeconds(60)).Until(d => ((javascriptexecutor)d).executescript("return document.readyState").Equals("complete")); 

if(wait == true)
{
    //Your code
}

以上语法可能会因python而改变

上面的代码将等待页面加载60秒,如果页面准备好(60秒内)则返回true,如果页面未准备好(60秒后)则返回false。