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.
Advertisement
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: