Selenium python find_element_by_class_name() stopped working from v 2.2 to 2.21 -- cannot use 'Compound Class Name'
Asked Answered
E

5

11

I am using Selenium's python library to scrape data from a html page in Firefox.

I have had to update from Selenium 2.0 to 2.21 because the server has updated Firefox.

In v 2.21 calls to find_element_by_class_name("grid-cell-inner grid-col-name") fails with:

selenium.common.exceptions.WebDriverException: Message: u'Compound class names not permitted'

The class name of the element I am trying to access is grid-cell-inner grid-col-name

The call to find_element_by_class_name() worked in v 2.2, so the logic is correct, and the data used to be found OK. Something changed in v 2.21.

All the Selenium examples give simple examples with class name foo etc, and none with the type of name I need to access.

Why did Selenium stop supporting finding classes with names like grid-cell inner grid-col-name, and what it their solution?

Can someone please help me to find elements with "compound" class names?

Europeanize answered 18/5, 2012 at 19:54 Comment(0)
T
15

The problem about WebDriver is that it still evolves. A lot. I personally don't know about a version that supported searching by many classes in one command, so it must have been a fairly old one :).

Searching by a CSS selector should work, however:

find_element_by_css_selector(".grid-cell-inner.grid-col-name");

I don't recommend using XPath for this particular thing, because these two following expressions are a different thing:

//*[class='grid-cell-inner grid-col-name']

//*[class='grid-col-name grid-cell-inner']

Twosome answered 20/5, 2012 at 11:2 Comment(4)
It is not searching by multiple classes; the class names in the html, over which I have no control, have spaces in them. If this is a "compound class name", then why stop supporting it? All our logic is now broken.Europeanize
Actually, no. It's two separate classes, grid-cell-inner and grid-col-name, I'm 100% positive on this. I don't know the reason behind Selenium not supporting searching by many class names - but I guess that's what CSS selectors are for. If it worked, it must have been some alpha or beta version, because I couldn't find any mention of this in any changelog. Go with the CSS selector solution, that should do it.Zion
A quick googling says this: To specify multiple classes, separate the class names with a space, e.g. <span class="left important">. This allows you to combine several CSS classes for one HTML element.Zion
Yes. Using find_element_by_css_selector() and specifying the class names as you described works OK. I only had to change a few lines of code to support this, and I can now find the elements. Thank you very much!Europeanize
N
7

You need to use a CssSelector in the format ".nameA.nameB.nameC" you can have as many as you'd like, just add the "."

Alternatively you can match the whole attribute (you can also do this with xpath): "[class='exact class name here']" XPath - "//[@class='exact class name here']"

There are ways to do starts with or ends with or contains too (in both CSS and xpath) which helps if the classes are generated dynamically.

Nautch answered 27/8, 2012 at 10:57 Comment(2)
Shouldn't this be "//*[@class='exact class name here']" ? Emphasis on the *Legate
So, should the * be present or not?Concrete
H
0

Selenium hasn't supported compound class names for a very long time I thought.

Needless to say, try via XPath or CSS selector or by the class name of "grid-cell-inner" then filtering to see what elements have the class of "grid-cell-inner grid-col-name".

Habitat answered 18/5, 2012 at 23:33 Comment(0)
H
0

also try:

elements = bot.execute_script("""return document.getElementsByClassName('grid-cell-inner grid-col-name')""")
Hemotherapy answered 5/10, 2014 at 19:1 Comment(0)
E
0

This error message...

selenium.common.exceptions.WebDriverException: Message: u'Compound class names not permitted'

...implies that locator strategies using Compound class names are no more valid while using Selenium.

Traces of this change can be observed from the Selenium v2.40.0 changelist where it mentions about adding proper error code for compound class name usage:

  • Implemented proper error code for the case of invalid css selector empty class name, and compound class name in atoms.

Solution

As an alternative you can use either of the following Locator Strategies:

  • Using CSS_SELECTOR:

    driver.find_element(By.CSS_SELECTOR, ".grid-cell-inner.grid-col-name")
    
  • Using XPATH:

    driver.find_element(By.XPATH, "//*[@class='grid-cell-inner grid-col-name']")
    

References

You can find a couple of relevant detailed discussion in:

Eighteenth answered 30/1, 2021 at 9:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.