1
votes

I am retrieving my link using the following code:

os.environ['MOZ_HEADLESS'] = '1'
binary = FirefoxBinary('C:\\Program Files\\Mozilla Firefox\\firefox.exe', log_file=sys.stdout)
self.driver = webdriver.Firefox(firefox_binary=binary, executable_path='C:/chromedriver/geckodriver')

self.driver.get(link)

Next, I call:

xpath=".//a[@class='tileLink']"
ignored_exceptions = (NoSuchElementException, StaleElementReferenceException,)

your_element = WebDriverWait(self.driver, 30, ignored_exceptions=ignored_exceptions).until(
                expected_conditions.presence_of_element_located((By.XPATH, xpath)))

and then

links = self.driver.find_elements_by_xpath(".//a[@class='tileLink']")
for link in links:
     href_ = link.get_attribute("href") # <<-- Error ehre

and link.get_attribute(attribute) throws the stale element exception.

Now, given the WebDriverWait I thought I would avoid this issue, yet it persists.

I am tempted to take the page source, once it has loaded, and throw it into lxml to avoid this issue completely.

The time the passes between establishing links and iterating over the links is a second at most.

Has anyone else experienced an issue like this, and found a solution?

Any guidance is appreciated.

2
I assume that some of the retrieved elements in the links list don't hold any href attributes, so you should use a try-except block to get rid of this problem. - Szabolcs
@Szabolcs Thanks, but then the exception would not be StaleElement, it would be something else completely. I do not think this is accurate. - jason m

2 Answers

0
votes

If I have understood your question you need to get the href attribute from all the elements identified with the xpath //a[@class='tileLink']. To achieve that you can use the following code block :

# xpath=".//a[@class='tileLink']"
# ignored_exceptions = (NoSuchElementException, StaleElementReferenceException,)
# links = WebDriverWait(self.driver, 30, ignored_exceptions=ignored_exceptions).until(expected_conditions.presence_of_element_located((By.XPATH, xpath)))
links = WebDriverWait(self.driver, 30).until(expected_conditions.visibility_of_all_elements_located((By.XPATH, "//a[@class='tileLink']")))
for link in links:
     print(link.get_attribute("href"))
0
votes

I had a similar problem with some movable buttons on the page being stale.

How about something like:

from selenium.common.exceptions import StaleElementReferenceException
from selenium.webdriver.common.action_chains import ActionChains

hrefs = []
for index, link in enumerate(links):
    attempts = 0
    while True:
        try:
            for action in range(0, 10):
                ActionChains(context.browser). \
                    move_to_element(links[index]).click().perform()
                href_ = link.get_attribute("href")
                if href_:
                    hrefs.append(href_)
                    break
            break
        except StaleElementReferenceException:
            attempts += 1
            if attempts > 10:
                break

I realise this is a very crude (primitive, even) solution, and assumes that the element becoming "un-stale" is a timing issue. I'm also not that good with Python, so this may need some tweaking...

Thinking about it, since those elements are links, perhaps you don't want to click them, in which case delete the click() bit from the ActionChains line, or perhaps change it to context_click().