0

My code:

from selenium import webdriver

driver = webdriver.Chrome(executable_path="D:\\Work\\chromedriver.exe")
driver.get("https://www.makemytrip.com/")
print(driver.title)
print(driver.current_url)
driver.find_element_by_css_selector(".fsw_inputField").click()  # Generating CSS from class name   
driver.find_element_by_css_selector("input[placeholder='From']").send_keys("chan")
cities = driver.find_elements_by_css_selector("p[class*='blackText']")
for city in cities:
    print(city.text)
    if city.text == "Chania, Greece":
        city.click()

Console Error:

Traceback (most recent call last):
  File "D:/Work/Python/FirstDemo/PythonSelenium/dyncamicDropdown.py", line 16, in <module>
    print(city.text)
  File "D:\Work\Python\FirstDemo\venv\lib\site-packages\selenium\webdriver\remote\webelement.py", line 76, in text
    return self._execute(Command.GET_ELEMENT_TEXT)['value']
  File "D:\Work\Python\FirstDemo\venv\lib\site-packages\selenium\webdriver\remote\webelement.py", line 633, in _execute
    return self._parent.execute(command, params)
  File "D:\Work\Python\FirstDemo\venv\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "D:\Work\Python\FirstDemo\venv\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
  (Session info: chrome=81.0.4044.138)
1
  • You should wait until the DOM is completely loaded. And is the element is in focus when you try to click?? If it is not in focus also you may get the Stale Element Exception.
    – Pratap
    May 15 '20 at 9:00
1

The above answer could help in making sure the elements are loaded properly. But the actual issue in your code is that you are not breaking the for loop after city.click()

So,

  1. You click dropdown
  2. You click city
  3. Dropdown closes
  4. For loop still continues and tries to iterate through stale objects

SO the fix:

if city.text == "Chania, Greece":
    city.click()
    break

Note: Added time.sleep() for waiting until the suggestions are loaded properly. You could use an explicit wait.

Final code:

from selenium import webdriver
import time

driver = webdriver.Chrome(executable_path="D:\\Work\\chromedriver.exe")
driver.get("https://www.makemytrip.com/")
print(driver.title)
print(driver.current_url)
driver.find_element_by_css_selector(".fsw_inputField").click()  # Generating CSS from class name   
driver.find_element_by_css_selector("input[placeholder='From']").send_keys("chan")
time.sleep(3);
cities = driver.find_elements_by_css_selector("p[class*='blackText']")
for city in cities:
    print(city.text)
    if city.text == "Chania, Greece":
        city.click()
        break

Output:

enter image description here

7
  • 1
    Fair point but I still get an StaleElementReferenceException when trying this code. Seems that the list of cities is still changing while the for loop is running.
    – Anonymous
    May 16 '20 at 16:58
  • @Anonymous try now :) add time.sleep()]
    – PDHide
    May 16 '20 at 18:08
  • Can you amend your code and confirm it solves the problem ?
    – Anonymous
    May 16 '20 at 18:19
  • @Anonymous amended try the new code
    – PDHide
    May 16 '20 at 18:20
  • 1
    Code work for me with sleep. Using Firefox on Linux.
    – Anonymous
    May 16 '20 at 18:26
0

The above postes is right.

Code like this is bound to fail because the page may be half-loaded (not all DOM elements will be loaded and ready).

You should ensure that the elements you are going to use are available. This is normally done with WebDriverWait.

Another important module in Selenium is Expected conditions. Among the conditions is staleness_of which could be useful in your scenario.

If you combine WebDriverWait with until (or until_not) plus expected_conditions you should be able to achieve something eg:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

element = driver.find_element_by_css_selector('.theselector')
WebDriverWait(driver=driver, timeout=10).until_not(EC.staleness_of(element))

Warning: note that in my code I am using find_element_by_css_selector and not find_elements_by_css_selector (plural).

References

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.