Finding elements by class name with Selenium in Python
Asked Answered
F

8

89

How can I filter elements that have the same class?

<html>
  <body>
    <p class="content">Link1.</p>
  </body>
</html>
<html>
  <body>
    <p class="content">Link2.</p>
  </body>
</html>
Fredrickafredrickson answered 2/5, 2015 at 12:29 Comment(0)
O
91

You can try to get the list of all elements with class = "content" by using find_elements_by_class_name:

a = driver.find_elements_by_class_name("content")

Then you can click on the link that you are looking for.

Occupancy answered 4/5, 2015 at 8:8 Comment(8)
Does it return all elements of the class or the first found?Corinthians
Why are you even initializing a as an empty list if you immediately reassign it?Coadjutrix
@keerthankumar this return list of all the elements. To get the 1st one use find_element_by_class_nameKeyes
You don't need the semicolon at the end of python line of code.Rhizotomy
Now how to click on the class name after selecting it? .click() attribute doesn't work!Helga
find_element_by_* and find_elements_by_* are removed in Selenium 4.3.0. Use find_element instead. Look at all change logs here.Miksen
@Parampreet Rai: Though find_element() throws an exception if the element doesn't exist.Brandtr
@PeterMortensen you can still use find_elements(By.CLASS_NAME, 'foo') to get a list of elementsGauleiter
M
55

By.CLASS_NAME was not yet mentioned:

from selenium.webdriver.common.by import By

driver.find_element(By.CLASS_NAME, "content")

This is the list of attributes which can be used as locators in By:

CLASS_NAME
CSS_SELECTOR
ID
LINK_TEXT
NAME
PARTIAL_LINK_TEXT
TAG_NAME
XPATH

Medan answered 17/6, 2020 at 7:40 Comment(3)
Thanks this worked for me. The alternative of using find_element_by_class_name wouldn't work at all for me, even if I used a wait.Sos
But it throws an exception if it doesn't exist(?). Thus disrupting the test run.Brandtr
Actually the question is for "elements" plural so driver.find_element(By.CLASS_NAME, "content") wouldn't get all right?Bordelaise
T
32

As per the HTML:

<html>
    <body>
    <p class="content">Link1.</p>
    </body>
<html>
<html>
    <body>
    <p class="content">Link2.</p>
    </body>
<html>

Two(2) <p> elements are having the same class content.

So to filter the elements having the same class i.e. content and create a list you can use either of the following Locator Strategies:

  • Using class_name:

    elements = driver.find_elements_by_class_name("content")
    
  • Using css_selector:

     elements = driver.find_elements_by_css_selector(".content")
    
  • Using xpath:

    elements = driver.find_elements_by_xpath("//*[@class='content']")
    

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

  • Using CLASS_NAME:

    elements = WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.CLASS_NAME, "content")))
    
  • Using CSS_SELECTOR:

    elements = WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, ".content")))
    
  • Using XPATH:

    elements = WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//*[@class='content']")))
    
  • 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 discussions in:

Turbinate answered 9/8, 2020 at 17:45 Comment(2)
Neither class name nor css selector worked, no idea why, but xpath did, thanks a lot for thatDecigram
From a comment: "find_element_by_* and find_elements_by_* are removed in Selenium 4.3.0. Use find_element instead."Brandtr
M
14

Use nth-child, for example: http://www.w3schools.com/cssref/sel_nth-child.asp

driver.find_element(By.CSS_SELECTOR, 'p.content:nth-child(1)')

or http://www.w3schools.com/cssref/sel_firstchild.asp

driver.find_element(By.CSS_SELECTOR, 'p.content:first-child')
Midiron answered 3/5, 2015 at 8:28 Comment(0)
S
12

The most simple way is to use find_element_by_class_name('class_name')

Salisbarry answered 4/5, 2015 at 7:49 Comment(0)
S
4

The first answer has been deprecated, and the other answers only return one result. This is the correct answer:

driver.find_elements(By.CLASS_NAME, "content")
Seddon answered 28/7, 2022 at 6:2 Comment(3)
Yes, they missed the plural, "elements". However, find_elements itself is deprecated.Brandtr
What do you mean by "the first answer"? Highest scored? Chronological first? References to relative positions of answers are not reliable as they depend on the view (votes/oldest/active) and changing of the accepted answer and change over time (for votes, active, and accepted state).Brandtr
To be fair, it wasn't missed in one of the answers.Brandtr
B
0

The question was related to "elements" plural, most are for element. To wait for the element and then iterate over each:

selectableEls = WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.CLASS_NAME, "content")))
for el in selectableEls:
    print(el)
Bordelaise answered 27/4, 2023 at 7:3 Comment(0)
A
-1

In Python, Selenium provides a method called find_elements_by_class_name to find elements with the same class name. This method returns a list of all elements that match the provided class name.

Let's say you're trying to find all paragraphs (

) with the class "content". Here's how you can do it:

from selenium import webdriver

initialize the driver

driver = webdriver.Firefox() # replace with the browser driver of your choice

navigate to your webpage

driver.get('https://www.softwaretestingsapiens.com/finding-elements-by-class-name-with-selenium-in-python/')

find elements by class name

elements = driver.find_elements_by_class_name('content')

for el in elements: print(el.text)

This script will print the text inside each

tag with the class "content". In your case, it should print "Link1." and "Link2.".

Remember, Selenium requires a specific driver to interface with the chosen browser. Firefox requires geckodriver, which needs to be installed before the above script can be run.

Also, keep in mind that find_elements_by_class_name returns a list, even if there's only one match. If you're certain there's only one element of interest, use find_element_by_class_name (note the lack of 's' in 'element') to get the WebElement directly.

Lastly, it's recommended to add some error handling to your script to manage situations where the elements are not found. This will make your code more robust and easier to debug.

Happy coding!

Astrea answered 2/12, 2023 at 3:32 Comment(1)
Are you aware of our policy forbidding AI-generated answers?Vogue

© 2022 - 2024 — McMap. All rights reserved.