我有两个列表:未使用的元素(填写)和使用过的元素。它们作为过滤器工作,我需要从第一个元素中选择元素,然后通过按钮或双击将它们添加到第二个元素。问题: 我可以使用代码简单地遍历第一个列表:
offers = app.driver.find_elements_by_tag_name('option')
for offer in offers:
if "21796" in offer.get_attribute("text"):
app.driver.find_elements_by_tag_name("option")offers.index(offer)].click()
在这种情况下,我会看到如何逐个选择优惠。但是当我尝试将选定的商品添加到第二个列表时:
offers = app.driver.find_elements_by_tag_name('option')
for offer in offers:
if "21796" in offer.get_attribute("text"):
app.driver.find_elements_by_tag_name("option")offers.index(offer)].click()
app.driver.find_element_by_name("add").click()
或
offers = app.driver.find_elements_by_tag_name('option')
double_click = ActionChains(app.driver)
for offer in offers:
if "21796" in offer.get_attribute("text"):
double_click.double_click(app.driver.find_elements_by_tag_name("option")[offers.index(offer)]).perform()
我收到错误:
for offer in offers:
> if "21796" in offer.get_attribute("text"):
...
if exception_class == ErrorInResponseException:
raise exception_class(response, message)
elif exception_class == UnexpectedAlertPresentException and 'alert' in value:
raise exception_class(message, screen, stacktrace, value['alert'].get('text'))
> raise exception_class(message, screen, stacktrace)
E StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
E (Session info: chrome=42.0.2311.90)
E (Driver info: chromedriver=2.9.248315,platform=Windows NT 6.3 x86_64)
为什么在&#34中添加第二个动作;如果"声明我失去了我们的生命?
答案 0 :(得分:1)
您遇到的问题是,在您处理列表时,可能会出现导致您正在查看的元素列表发生变化的问题。这完全取决于您正在访问的页面中运行的JavaScript,您没有显示。请注意,即使从您的角度来看,您没有看到列表更改,但某些实现会将事件视为点击以刷新其列表,如果要显示的数据实际上没有更改,他们可能仍然用新的DOM元素替换构成列表的所有DOM元素,这些元素看起来与旧的元素完全相同。因此,即使列表看起来相同,列表中的DOM元素也是新的,这会导致像你这样的Selenium代码出现问题。这似乎可能会触发列表刷新:app.driver.find_element_by_name("add").click()
当您执行app.driver.find_elements_by_tag_name("option")[offers.index(offer)].click()
时重新获取列表但是在执行offer.get_attribute("text")
时没有重新获取列表,因此此命令可能引用文档中不再存在的DOM元素,以及Selenium chokes
您的问题中没有显示足够的信息来确定解决问题的解决方案和在执行您想要的任务时效率最高。您可以将offer
的所有实例替换为app.driver.find_elements_by_tag_name("option")[offers.index(offer)]
,但这样效率会非常低。如果唯一改变列表的是点击"add"
按钮,那么这样的事情应该有效:
offers = app.driver.find_elements_by_tag_name('option')
for x in range(0, len(offers)):
if "21796" in offer[x].get_attribute("text"):
offers[x].click()
app.driver.find_element_by_name("add").click()
# Reacquire the list after adding!
offers = app.driver.find_elements_by_tag_name('option')
上面的代码假设更改列表的唯一方法是单击"add"
按钮。它还假设除了陈旧的元素问题,您的原始代码是正确的。并且不可能有更有效的方法来做到这一点,但这取决于问题中没有的细节。