pythonseleniumselenium-webdriverxpathstaleelementreferenceexception

Why getting this Error selenium.common.exceptions.StaleElementReferenceException:


I know already upload answer to this same question but I try them they are not working for me because there is also some some update in selenium code too.

selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
  (Session info: chrome=108.0.5359.95)

When trying to send my searching keyword in this input with label "Skills Search" in advance searching pop-pup form.

Here is the URL: https://www.upwork.com/nx/jobs/search/modals/advanced-search?sort=recency&pageTitle=Advanced%20Search&_navType=modal&_modalInfo=%5B%7B%22navType%22%3A%22modal%22,%22title%22%3A%22Advanced%20Search%22,%22modalId%22%3A%221670133126002%22,%22channelName%22%3A%22advanced-search-modal%22%7D%5D

Here is my code:

import time

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

options = Options()
options.add_argument("start-maximized")

webdriver_service = Service('F:\\work\\chromedriver_win32\\chromedriver.exe')
driver = webdriver.Chrome(options=options, service=webdriver_service)
wait = WebDriverWait(driver, 10)

url = "https://www.upwork.com/nx/jobs/search/?sort=recency"
driver.get(url)

key = ["Web Scraping","Selenium WebDriver", "Data Scraping", "selenium", "Web Crawling", "Beautiful Soup", "Scrapy", "Data Extraction", "Automation"]
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'button#onetrust-accept-btn-handler')))
time.sleep(5)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'button#onetrust-accept-btn-handler'))).click()
for i in range(len(key)):
    wait.until(EC.element_to_be_clickable((By.XPATH, '//button[contains(@title,"Advanced Search")]'))).click()
    time.sleep(5)
    advanced_search_input = driver.find_element(By.XPATH,'//input[contains(@aria-labelledby,"tokenizer-label")]')
    # advanced_search_input.click()
    advanced_search_input.send_keys(key[i])

enter image description here

result giving now enter image description here


Solution

  • By clicking '//input[contains(@aria-labelledby,"tokenizer-label")]' element it is re-built on the page (really strange approach they built that page).
    To make this code working I added a delay after clearing and clicking that input and then get that element again.
    The following code worked for me:

    import time
    
    from selenium import webdriver
    from selenium.webdriver.chrome.service import Service
    from selenium.webdriver.chrome.options import Options
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    
    options = Options()
    options.add_argument("start-maximized")
    
    webdriver_service = Service('C:\webdrivers\chromedriver.exe')
    driver = webdriver.Chrome(options=options, service=webdriver_service)
    wait = WebDriverWait(driver, 10)
    
    url = "https://www.upwork.com/nx/jobs/search/?sort=recency"
    driver.get(url)
    
    keys = ["Web Scraping","Selenium WebDriver", "Data Scraping", "selenium", "Web Crawling", "Beautiful Soup", "Scrapy", "Data Extraction", "Automation"]
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'button#onetrust-accept-btn-handler')))
    time.sleep(5)
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'button#onetrust-accept-btn-handler'))).click()
    for i in range(len(keys)):
        wait.until(EC.element_to_be_clickable((By.XPATH, '//button[contains(@title,"Advanced Search")]'))).click()
        wait.until(EC.element_to_be_clickable((By.XPATH,'//input[contains(@aria-labelledby,"tokenizer-label")]'))).clear()
        wait.until(EC.element_to_be_clickable((By.XPATH, '//input[contains(@aria-labelledby,"tokenizer-label")]'))).click()
        time.sleep(3)
        wait.until(EC.element_to_be_clickable((By.XPATH, '//input[contains(@aria-labelledby,"tokenizer-label")]'))).send_keys(keys[i])
        wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'[data-test="modal-advanced-search-search-btn"]'))).click()
    

    UPD
    In order to select multiple search values you need to insert each value, select the appearing autocomplete option and continue, as in the code below:

    import time
    
    from selenium import webdriver
    from selenium.webdriver.chrome.service import Service
    from selenium.webdriver.chrome.options import Options
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    
    options = Options()
    options.add_argument("start-maximized")
    
    webdriver_service = Service('C:\webdrivers\chromedriver.exe')
    driver = webdriver.Chrome(options=options, service=webdriver_service)
    wait = WebDriverWait(driver, 10)
    
    url = "https://www.upwork.com/nx/jobs/search/?sort=recency"
    driver.get(url)
    
    keys = ["Web Scraping", "Selenium WebDriver", "Data Scraping", "Selenium", "Beautiful Soup", "Scrapy", "Data Extraction", "Automation"] #
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'button#onetrust-accept-btn-handler')))
    time.sleep(5)
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'button#onetrust-accept-btn-handler'))).click()
    wait.until(EC.element_to_be_clickable((By.XPATH, '//button[contains(@title,"Advanced Search")]'))).click()
    wait.until(EC.element_to_be_clickable((By.XPATH,'//input[contains(@aria-labelledby,"tokenizer-label")]'))).clear()
    wait.until(EC.element_to_be_clickable((By.XPATH, '//input[contains(@aria-labelledby,"tokenizer-label")]'))).click()
    time.sleep(3)
    for i in range(len(keys)):
        wait.until(EC.element_to_be_clickable((By.XPATH, '//input[contains(@aria-labelledby,"tokenizer-label")]'))).send_keys(keys[i])
        time.sleep(2)
        wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#typeahead-input-control-35 .up-menu-item-text"))).click()
        time.sleep(4)
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'[data-test="modal-advanced-search-search-btn"]'))).click()
    

    UPD
    Finally did it!
    The problem with wrong inputs caused by too slow response time of that page.
    To make it working I inserted a small delay between inserting each character of the input string. In this case the result is as expected.
    This is the final working code:

    import time
    
    from selenium import webdriver
    from selenium.webdriver.chrome.service import Service
    from selenium.webdriver.chrome.options import Options
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    
    options = Options()
    options.add_argument("start-maximized")
    
    webdriver_service = Service('C:\webdrivers\chromedriver.exe')
    driver = webdriver.Chrome(options=options, service=webdriver_service)
    wait = WebDriverWait(driver, 10)
    
    url = "https://www.upwork.com/nx/jobs/search/?sort=recency"
    driver.get(url)
    
    keys = ["Web Scraping", "Selenium Webdriver", "Data Scraping", "Selenium", "Beautiful Soup", "Scrapy", "Data Extraction", "Automation"]
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'button#onetrust-accept-btn-handler')))
    time.sleep(5)
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'button#onetrust-accept-btn-handler'))).click()
    wait.until(EC.element_to_be_clickable((By.XPATH, '//button[contains(@title,"Advanced Search")]'))).click()
    wait.until(EC.element_to_be_clickable((By.XPATH,'//input[contains(@aria-labelledby,"tokenizer-label")]'))).clear()
    wait.until(EC.element_to_be_clickable((By.XPATH, '//input[contains(@aria-labelledby,"tokenizer-label")]'))).click()
    time.sleep(3)
    for i in range(len(keys)):
        search_field = wait.until(EC.element_to_be_clickable((By.XPATH, '//input[contains(@aria-labelledby,"tokenizer-label")]')))
        search_field.click()
        for character in keys[i]:
            search_field.send_keys(character)
            time.sleep(0.05)
        time.sleep(2)
        wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#typeahead-input-control-35 .up-menu-item-text"))).click()
        time.sleep(2)
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'[data-test="modal-advanced-search-search-btn"]'))).click()
    

    The result is

    enter image description here