Search code examples
pythonhtmlseleniumselenium-chromedriverstaleelementreferenceexception

Message: stale element reference: element is not attached to the page document while refreshing TABLE DATA


First of all, sorry for my bad english. I have a project to retrieve row data in a table continuously using

driver.refresh()

The first loop is successful, the data appears for each row. Now for the 2nd loop a message appears

Message: stale element reference: element is not attached to the page document

For some reason it seems like the DOM on the page changes after a refresh. I've been looking for a solution on the internet and still don't understand how to implement it in my code. Can anyone help? Thank you.

table = wait(driver, 10).until(EC.presence_of_element_located((By.XPATH,
                                                               "/html/body/div[1]/div["
                                                               "1]/section/section/section/main/section/section/div["
                                                               "2]/div/div[2]/div[1]/div/div[2]/table")))
while True:
    for i in wait(table, 999).until(EC.presence_of_all_elements_located((By.XPATH, ".//tbody/tr"))):
        tr = [tr.text for tr in i.find_elements(By.XPATH, ".//td")]
        if tr[2] == "Done":
            print(tr[1] + "\n" + tr[2] + "\n" + tr[9] + "\n" + tr[15] + "\n" + tr[19] + "\n")
    driver.refresh()

Solution

  • As you understand, and it is correct, after refreshing all the web elements on the page are being re-rendered. Selenium WebEelement is actually a pointer, a reference to a physical web element on the actual web page. So, after the page was re-built all the previously collected WebElements become no more relevant. In the Selenium terminology they become Stale elements.
    So, to make your code working you have to get all the elements you are going to iterate over again.
    I can't give you tested code since you didn't share a link to that page, but I guess the following should work:

    table = wait(driver, 10).until(EC.presence_of_element_located((By.XPATH,
                                                                   "/html/body/div[1]/div["
                                                                   "1]/section/section/section/main/section/section/div["
                                                                   "2]/div/div[2]/div[1]/div/div[2]/table")))
    while True:
        for i in wait(table, 999).until(EC.presence_of_all_elements_located((By.XPATH, ".//tbody/tr"))):
            tr = [tr.text for tr in i.find_elements(By.XPATH, ".//td")]
            if tr[2] == "Done":
                print(tr[1] + "\n" + tr[2] + "\n" + tr[9] + "\n" + tr[15] + "\n" + tr[19] + "\n")
        driver.refresh()
        table = wait(driver, 10).until(EC.presence_of_element_located((By.XPATH,
                                                                   "/html/body/div[1]/div["
                                                                   "1]/section/section/section/main/section/section/div["
                                                                   "2]/div/div[2]/div[1]/div/div[2]/table")))
    

    Also, you have to improve your locators.
    "/html/body/div[1]/div[1]/section/section/section/main/section/section/div[2]/div/div[2]/div[1]/div/div[2]/table" locator must be improved