Reputation: 117
Hi i would like to write registration bot.
I am using selenium with python and at the beginning I have encountered following problem.
elems = driver.find_elements_by_xpath("//a[@href]")
for elem in elems:
elem_ = elem.get_attribute("href")
regex = re.compile('signup')
match = re.search(regex, elem_)
if match:
print(elem_)
elem.click()
with that i am able to find registration link, but when i try to click it it gives me:
Message: stale element reference: element is not attached to the page document
am i badly accesing the element? how to execute click function on element from list created by find_elements_by_something?
Upvotes: 3
Views: 425
Reputation: 2425
The way you are executing the click function is correct: the find_elements function return a list of WebElements and you call the click function of one of its elements. The problem resides elsewhere.
Docs: Stale Element Reference Exception
A stale element reference exception is thrown in one of two cases, the first being more common than the second:
The element has been deleted entirely.
The element is no longer attached to the DOM.
As you can see the exception is thrown the moment selenium is unable to locate the element int the DOM structure.
A generic solution to this problem does not exists as it depends on the web page you are working on.
Generally this kind of problems occurs in dynamic pages where, as the name implies, the DOM structure is generate dynamically.
As simple it may seems a common solution is to try again, just surrounds it in a try block and re-execute the code:
from selenium.common.exceptions import StaleElementReferenceException
try:
...
except StaleElementReferenceException:
...
In the worst case scenario, if the only action that you have to perform is the button click(), you could work-around the DOM moving to an element by coordinates, via an ActionChain.
from selenium.webdriver.common.action_chains import ActionChains
elem = driver.find_element(By.TAG_NAME, 'body')
ac = ActionChains(driver)
ac.move_to_element(elem).move_by_offset(x_offset, y_offset).click().perform()
Upvotes: 1