Selenium和Python:在select中显式等待回发(使用Selenium等待Javascript)
我正在尝试使用Python和Selenium选择列表中的各种元素。Selenium和Python:在select中显式等待回发(使用Selenium等待Javascript),javascript,python,selenium-webdriver,Javascript,Python,Selenium Webdriver,我正在尝试使用Python和Selenium选择列表中的各种元素。类在Javascript中附带了一个Postback,类似于: onchange="javascript:setTimeout('__doPostBack(\'dum1$dum2$dum3$ListBoxThingsToSelect\',\'\')', 0)" 当我尝试使用Selenium选择一个值时,它只对第一个值有效,然后DOM发生更改,我得到一个StaleElementReferenceException:Element不
类在Javascript中附带了一个Postback
,类似于:
onchange="javascript:setTimeout('__doPostBack(\'dum1$dum2$dum3$ListBoxThingsToSelect\',\'\')', 0)"
当我尝试使用Selenium选择一个值时,它只对第一个值有效,然后DOM发生更改,我得到一个StaleElementReferenceException:Element不再附加到DOM
错误
因此,我尝试在单击该元素之前等待该元素变为可用。我使用以下代码和预期条件(EC)执行此操作:
这有时适用于选择多个值,但在某些情况下,可能无法单击(未单击该值),或者再次导致StaleElementReferenceException:元素不再附加到DOM
错误。有人能帮忙吗?我的理论是select元素是可以定位和单击的,但是页面会继续加载,因为要加载的select元素更多。因此,DOM发生了变化,当我尝试elem1.click()
时,DOM发生了变化
我如何等待整个字段被加载?
postback
的具体功能是什么?
很不幸我不能发布一个链接到页面,它是内部的
EDIT1
vals\u deselect
是我要取消选择的索引的索引列表。然后将这些索引粘贴到循环中的XPATH
,以从select中选择特定选项。
vals\u deselect=[1,4,5,7,9,12]
EDIT2
我还尝试了以下方法:
print("jQuery.active: " + str(browser.execute_script("return jQuery.active")))
print("readyState: " + browser.execute_script("return document.readyState"))
WebDriverWait(browser, 100).until(EC.element_to_be_clickable((By.XPATH,
"/html/body/form/div[11]/div[2]/fieldset/center/table/tbody/tr[3]/td[3]/select[2]/option[" + str(row)+ "]"))).click()
它总是显示jquery.active
为0,而readyState
为complete
。我非常想解决这个问题。我想通过检查readyState
和jquery.active
可以检查回发是否完成。有人有什么想法吗
回发内容与此页面上的内容完全相同:
我需要等待它完成,但我该怎么做呢?试试这个
from selenium.webdriver.common.action_chains import ActionChains
for row in vals_deselect:
while not browser.execute_script("return document.readyState")== "complete":
continue
else:
WebDriverWait(browser, 100).until(EC.element_to_be_clickable((
By.XPATH, "/html/body/form/div[11]/div["
"2]/fieldset/center/table/tbody/tr[3]/td[3]/select["
"2]/option[" + str(row) + "]")))
ActionChains(browser).move_to_element(elem1).click().perform()
如果每次选择选项后都会刷新
,则可以使用预期条件。您还应该使用从
标记中选择一个选项
for row in vals_deselect:
selectElement = driver.find_element_by_xpath("/html/body/form/div[11]/div[2]/fieldset/center/table/tbody/tr[3]/td[3]/select[2]")
Select(selectElement).deselect_by_index(row)
WebDriverWait(browser, 100).until(EC.staleness_of(selectElement))
作为旁注,您应该避免在xpath
中使用绝对路径。尝试在html层次结构中为您要查找的元素找到尽可能接近的唯一标识符
更新
回答评论中的问题
你能给我解释一下这是怎么回事吗?元素变得陈旧这一事实是否意味着回发已经完成?另外,您能解释一下您对xpath的评论是什么意思吗
WebElement
在刷新或更改时会过时,这意味着即使它看起来完全相同(与您的情况类似)或已删除,也会有一个新元素。当整个DOM被刷新或更改时,或者仅当一个特定元素被刷新或更改时,就会发生这种情况EC.
的staleness_将等待元素不再附加到DOM,或者直到定义的时间结束
有几个原因不使用绝对xpath
。性能(比相对xpath
或类似find\u element\u by\u id
的方法慢得多)、可读性和脆弱性(想象有人在
之前添加了
标记。绝对xpath
将失败,相对仍能工作) 你好,谢谢你的回答。Myvals\u deselect
是一个字符串列表,其中包含我希望取消选择的选项的文本。没有方法get\u vals\u deselect()
。这可能是错误的原因吗?非常感谢您的帮助。您是说vals\u deselectis
是一个静态列表吗?是的,它是。不应该吗?不可以,它包含字符串列表??你能举一个这个列表的例子吗?对不起,这是一个索引列表,指定要取消选择的选项。请看上面的EDIT1。我试过你的方法。但是我得到一个错误,声明AttributeError:“Select”对象没有属性“已启用”
这是否意味着无法检查Select的过时性。此外,我还应该提到,我正在尝试按索引取消选择
,以防万一,最初列表中的所有值都被选中。@rashid我已经更新了答案。select
和deselect
的用法是一样的,这不是问题。这很有效。多谢各位。在我接受答案之前,请你向我解释一下这是怎么回事好吗?元素过时的事实是否意味着回发已经完成?另外,请您解释一下您对xpath
的评论是什么意思?@rashid我在回答中添加了一个解释。太棒了,非常感谢。我接受了你的回答,把赏金交给了你。哈哈,我来之不易的名声消失了:),我只能在20小时内分配赏金。我会这样做。
for row in vals_deselect:
selectElement = driver.find_element_by_xpath("/html/body/form/div[11]/div[2]/fieldset/center/table/tbody/tr[3]/td[3]/select[2]")
Select(selectElement).deselect_by_index(row)
WebDriverWait(browser, 100).until(EC.staleness_of(selectElement))