Why selenium dont find tag and class

Tags: , , , ,



I recently started using selenium and I can’t solve one problem. When I use find_element_by_tag(class)_name or _css_selector raise error:

selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element:

But the element I’m looking for exists.

For example:

from selenium import webdriver

from webdriver_manager.chrome import ChromeDriverManager

browser = webdriver.Chrome(ChromeDriverManager().install())
url='http://inventwithpython.com/'
browser.get(url)
a = browser.find_element_by_class_name('navbar navbar-toggleable-md')

Output:

[WDM] - Current google-chrome version is 85.0.4183
 
[WDM] - Get LATEST driver version for 85.0.4183
[WDM] - Driver [C:Usersvladv.wdmdriverschromedriverwin3285.0.4183.87chromedriver.exe] found in cache
Traceback (most recent call last):
  File "C:/Users/vladv/PycharmProjects/untitled1/черновик.py", line 14, in <module>
    a = browser.find_element_by_class_name('navbar navbar-toggleable-md')
  File "C:UsersvladvAppDataLocalProgramsPythonPython37libsite-packagesseleniumwebdriverremotewebdriver.py", line 564, in find_element_by_class_name
    return self.find_element(by=By.CLASS_NAME, value=name)
  File "C:UsersvladvAppDataLocalProgramsPythonPython37libsite-packagesseleniumwebdriverremotewebdriver.py", line 978, in find_element
    'value': value})['value']
  File "C:UsersvladvAppDataLocalProgramsPythonPython37libsite-packagesseleniumwebdriverremotewebdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "C:UsersvladvAppDataLocalProgramsPythonPython37libsite-packagesseleniumwebdriverremoteerrorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":".navbar navbar-toggleable-md"}
  (Session info: chrome=85.0.4183.102)

But if I want to find “navbar-brand” class, I can do it. What’s the problem?

And if I use find_elements, return empty list.

P.S If somebody can advise some useful material for studying selenium it’ll be very helpful.

Answer

As per the documentation of selenium.webdriver.common.by implementation:

class selenium.webdriver.common.by.By
    Set of supported locator strategies.

    CLASS_NAME = 'class name'
    

So, using find_element_by_class_name() you won’t be able to pass multiple class names. Passing multiple classes you will face an error.


Solution

To locate the element you can use either of the following Locator Strategies:

  • Using css_selector:

    element = driver.find_element_by_css_selector("nav.navbar.navbar-toggleable-md")
    
  • Using xpath:

    element = driver.find_element_by_xpath("//nav[@class='navbar navbar-toggleable-md']")
    

Ideally, to locate the element you need to induce WebDriverWait for the visibility_of_element_located() and you can use either of the following Locator Strategies:

  • Using CSS_SELECTOR:

    element = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "nav.navbar.navbar-toggleable-md")))
    
  • Using XPATH:

    element = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//nav[@class='navbar navbar-toggleable-md']")))
    
  • Note : You have to add the following imports :

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    

References

You can find a couple of relevant detailed discussions in:



Source: stackoverflow