Selenium stale element reference in for loop

Viewed 632

I Used Windows10, Chrome version 89.0.4389.9, vscode, python

This code only loops once then errors with the error below.

table = driver.find_element_by_xpath('//*[@id="frm"]/table')
tbody = table.find_element_by_tag_name("tbody")
rows = tbody.find_elements_by_tag_name("tr")
# btns = driver.find_element_by_xpath('//*[@id="frm"]/table/tbody/tr[*]/td[2]/a')

for index, value in enumerate(rows):
    body=value.find_elements_by_tag_name("td")[1]

    body.click()
    sleep(2)
    
    driver.back()
    sleep(2)
Traceback (most recent call last):
  File "d:/Study/Companylist/program/pandastest.py", line 80, in <module>
    body=value.find_elements_by_tag_name("td")[1]
  File "D:\Anaconda\lib\site-packages\selenium\webdriver\remote\webelement.py", line 320, in find_elements_by_tag_name
    return self.find_elements(by=By.TAG_NAME, value=name)
  File "D:\Anaconda\lib\site-packages\selenium\webdriver\remote\webelement.py", line 684, in find_elements
    return self._execute(Command.FIND_CHILD_ELEMENTS,
  File "D:\Anaconda\lib\site-packages\selenium\webdriver\remote\webelement.py", line 633, in _execute
    return self._parent.execute(command, params)
  File "D:\Anaconda\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "D:\Anaconda\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
3 Answers

I don't use selenium, but I believe the problem is that the element is no longer in the DOM. To get around this, you could use a "try" block.

try:
    body=value.find_elements_by_tag_name("td")[1]
    #some code
except:
    pass

Seems like I found the solution, but can protect it that it's the best, will dig into it more:

elements = driver.find_elements(By.CSS_SELECTOR, 'div.g')
for n, el in enumerate(elements):
    elements = driver.find_elements(By.CSS_SELECTOR, 'div.g')
    elements[n].click()
    time.sleep(1)
    driver.back()
    time.sleep(1)
driver.quit()

try to find elements, then move start the loop and find the same result and get items from that loop by item number from enumarate function.

from time import sleep
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains

def company_info(driver):
    com_name = driver.find_element_by_xpath('Enter your site xpath')
    print(com_name.text)

    com_addr = driver.find_element_by_xpath('Enter your site xpath')
    print(com_addr.text)

    com_tel = driver.find_element_by_xpath('Enter your site xpath')
    print(com_tel.text)

    com_fax = driver.find_element_by_xpath('Enter your site xpath')
    print(com_fax.text)

driver = webdriver.Chrome()
url_search = 'Enter your site URL'

    #input values
web_open_wait = 5
web_close_wait = 3
driver.get(url_search)
sleep(web_open_wait)

check_names = driver.find_elements_by_xpath('//*[@id="frm"]/table/tbody/tr[1]/td/a'
for n, el in enumarate(check_names, start=1):
    check_names = driver.find_elements_by_xpath('//*[@id="frm"]/table/tbody/tr[%d]/td/a' % n)
    check_name[el].click()

    company_info(driver)
    driver.back()

driver.quit()

We will find the answer. Like we always do

I was thinking of the code I just put on top, and I came up with this method when I was thinking about how to fix @Vovo, one of the hints you gave me that rows couldn't come in repeatedly. It doesn't look pretty, but it works well.

(It is difficult to use two drivers because the site I open cannot click the control.)

Anyway. Share. Hope it helps if someone sees this.

What I was trying to make is, Enter the site containing the company information, Among the publicly available information, I was trying to extract the company name, address, contact information, and fax number.

The order of operation is: Site access> Set xpath path of desired data> Click> Extract> End site

It's repeating this cycle As much as i want

For reference, the sites I open are like Control + Cilck or something like that. If you click it, you have to load the element unconditionally. Go back or go forward, so it keeps hurting. It would be comfortable to open it up and extract it and turn it off and extract it and turn it off. If there is any improvement, please tell me

from time import sleep
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains

def company_info():
    com_name = driver.find_element_by_xpath('Enter your site xpath')
    print(com_name.text)

    com_addr = driver.find_element_by_xpath('Enter your site xpath')
    print(com_addr.text)

    com_tel = driver.find_element_by_xpath('Enter your site xpath')
    print(com_tel.text)

    com_fax = driver.find_element_by_xpath('Enter your site xpath')
    print(com_fax.text)

num_add = 0
while True:
    driver = webdriver.Chrome()
    url_search = 'Enter your site URL'

    #input values
    web_open_wait = 5
    web_close_wait = 3

    # Url Open
    driver.get(url_search)
    sleep(web_open_wait)

    # Collect info
    num_add += 1
    check_name = driver.find_element_by_xpath('//*[@id="frm"]/table/tbody/tr[{0}]/td[2]/a'.format(num_add))
    check_name.click()

    sleep(web_open_wait)
    company_info()

    # Url Close
    driver.quit()
Related