Checking if element exists with Python Selenium

PythonHtmlSeleniumWebdriver

Python Problem Overview


I have a problem - I am using the selenium (firefox) web driver to open a webpage, click a few links etc. then capture a screenshot.

My script runs fine from the CLI, but when run via a cronjob it is not getting past the first find_element() test. I need to add some debug, or something to help me figure out why it is failing.

Basically, I have to click a 'log in' anchor before going to the login page. The construct of the element is:

<a class="lnk" rel="nofollow" href="/login.jsp?destination=/secure/Dash.jspa">log in</a>

I am using the find_element By LINK_TEXT method:

login = driver.find_element(By.LINK_TEXT, "log in").click()

I am a bit of a Python Noob, so I am battling with the language a bit...

A) How do I check that the link is actually being picked up by python? Should I use try/catch block?

B) Is there a better/more reliable way to locate the DOM element than by LINK_TEXT? E.g. In JQuery, you can use a more specific selector $('a.lnk:contains(log in)').do_something();


I have solved the main problem and it was just finger trouble - I was calling the script with incorrect parameters - Simple mistake.

I'd still like some pointers on how to check whether an element exists. Also, an example/explanation of implicit / explicit Waits instead of using a crappy time.sleep() call.

Cheers, ns

Python Solutions


Solution 1 - Python

a)

from selenium.common.exceptions import NoSuchElementException        
def check_exists_by_xpath(xpath):
    try:
        webdriver.find_element_by_xpath(xpath)
    except NoSuchElementException:
        return False
    return True

b) use xpath - the most reliable. Moreover you can take the xpath as a standard throughout all your scripts and create functions as above mentions for universal use.

UPDATE: I wrote the initial answer over 4 years ago and at the time I thought xpath would be the best option. Now I recommend to use css selectors. I still recommend not to mix/use "by id", "by name" and etc and use one single approach instead.

Solution 2 - Python

None of the solutions provided seemed at all easiest to me, so I'd like to add my own way.

Basically, you get the list of the elements instead of just the element and then count the results; if it's zero, then it doesn't exist. Example:

if driver.find_elements_by_css_selector('#element'):
    print "Element exists"

Notice the "s" in find_elements_by_css_selector to make sure it can be countable.

EDIT: I was checking the len( of the list, but I recently learned that an empty list is falsey, so you don't need to get the length of the list at all, leaving for even simpler code.

Also, another answer says that using xpath is more reliable, which is just not true. See https://stackoverflow.com/questions/16788310/what-is-the-difference-between-css-selector-xpath-which-is-betteraccording-t

Solution 3 - Python

A) Yes. The easiest way to check if an element exists is to simply call find_element inside a try/catch.

B) Yes, I always try to identify elements without using their text for 2 reasons:

  1. the text is more likely to change and;
  2. if it is important to you, you won't be able to run your tests against localized builds.

solution either:

  1. You can use xpath to find a parent or ancestor element that has an ID or some other unique identifier and then find it's child/descendant that matches or;
  2. you could request an ID or name or some other unique identifier for the link itself.

For the follow up questions, using try/catch is how you can tell if an element exists or not and good examples of waits can be found here: http://seleniumhq.org/docs/04_webdriver_advanced.html

Solution 4 - Python

Solution without try&catch and without new imports:

if len(driver.find_elements_by_id('blah')) > 0: #pay attention: find_element*s*
    driver.find_element_by_id('blah').click #pay attention: find_element

Solution 5 - Python

The same as Brian, but add to this answer from tstempko:

https://sqa.stackexchange.com/questions/3481/quicker-way-to-assert-that-an-element-does-not-exist

So I tried and it works quickly:

driver.implicitly_wait(0)

if driver.find_element_by_id("show_reflist"):        
 driver.find_element_by_id("show_reflist").find_element_by_tag_name("img").click()

after this I restore my default value

driver.implicitly_wait(30)

Solution 6 - Python

You could also do it more concisely using

driver.find_element_by_id("some_id").size != 0

Solution 7 - Python

driver.find_element_by_id("some_id").size() is class method.

What we need is :

driver.find_element_by_id("some_id").size which is dictionary so :

if driver.find_element_by_id("some_id").size['width'] != 0 : print 'button exist'

Solution 8 - Python

you could use is_displayed() like below

res = driver.find_element_by_id("some_id").is_displayed()
assert res, 'element not displayed!'

Solution 9 - Python

When you know the element could not be there, the implicit wait could be a problem. I've created a simple context manager to avoid those waiting times

class PauseExplicitWait(object):
    """
    Example usage:

    with PauseExplicitWait(driver, 0):
        driver.find_element(By.ID, 'element-that-might-not-be-there')
    """
    def __init__(self, driver, new_wait=0):
        self.driver = driver
        self.original_wait = driver.timeouts.implicit_wait
        self.new_wait = new_wait
      
    def __enter__(self):
        self.driver.implicitly_wait(self.new_wait)
  
    def __exit__(self, exc_type, exc_value, exc_tb):
        self.driver.implicitly_wait(self.original_wait)
  

Solution 10 - Python

With the latest Selenium, you can now use you can now use .is_displayed():

https://www.selenium.dev/documentation/webdriver/elements/information/

Solution 11 - Python

You can find elements by available methods and check response array length if the length of an array equal the 0 element not exist.

element_exist = False if len(driver.find_elements_by_css_selector('div.eiCW-')) > 0 else True

Solution 12 - Python

You can check by find_elements, if the result is null, that element is not exist

if driver.find_elements(By.SOMETHING, "#someselector") == []:
    continue   # that element is not exist

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnonshatterView Question on Stackoverflow
Solution 1 - PythonAlex OkrushkoView Answer on Stackoverflow
Solution 2 - PythonBrian LeishmanView Answer on Stackoverflow
Solution 3 - PythonSam WoodsView Answer on Stackoverflow
Solution 4 - PythonSuper MarioView Answer on Stackoverflow
Solution 5 - PythonvmkView Answer on Stackoverflow
Solution 6 - PythoncodeslordView Answer on Stackoverflow
Solution 7 - PythonLopi DaniView Answer on Stackoverflow
Solution 8 - PythonRajesh SelvarajView Answer on Stackoverflow
Solution 9 - PythonkirilView Answer on Stackoverflow
Solution 10 - PythonRaoulView Answer on Stackoverflow
Solution 11 - PythonWebLab - groupView Answer on Stackoverflow
Solution 12 - Pythonbao.leView Answer on Stackoverflow