1

How can I handle multiple <img> elements in Selenium when all of them have the same id attribute?
I need a way to automatically detect and interact with these images, even though they share the same ID and only the image source (src) is different.

New contributor
rocksaketh is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
4
  • Please provide enough code so others can better understand or reproduce the problem. Commented Nov 25 at 9:29
  • 1
    Use an attribute selector? driver.findElements(By.cssSelector("[id='foobar']")); Commented Nov 25 at 9:31
  • 1
    @C3roe That's no different than using By.id('foobar'). You still find ALL the IMG tags with that ID. Commented Nov 25 at 22:27
  • 1
    This question needs details. "Detect and interact" how, exactly? Commented Nov 26 at 0:16

3 Answers 3

2

Ideally you would use a CSS selector and specify not only the ID but also the full or partial src, e.g.

img#test[src^='https://stackoverflow.com']
^ an IMG tag
    ^ that has an ID of 'test'
        ^ that has a 'src' starting with (^=) the string, 'https://stackoverflow.com'

Common string operators include,

^= starts with
$= ends with
*= contains

There are more listed in the spec, https://www.w3.org/TR/selectors/#overview, and a whole lot more info on CSS selectors in general.

Sign up to request clarification or add additional context in comments.

4 Comments

I'd be concerned that an #id selector would only return a single result, similar to how document.getElementById() does. An [id='test'] attribute selector may be required instead
Nope... single or multiple element returns depends on .findElement() or .findElements() (and the HTML, of course). document.getElementById() is specifically Element (singular) not Elements (plural). Selenium turns By.Id() into a CSS selector in the background anyway.
Yep, I saw that part about By.id() but it wasn't clear if #id behaves the same
...and if, for some reason they all have the same src, you could fallback to using a partially path based locator. Having non-unique IDs is a bug, though, and should be written up.
0

Yeap,​‍​‌‍​‍‌​‍​‌‍​‍‌ that kind of thing occurs when a website uses the same id for different elements multiple times (which really shouldn't be the case, but anyway). Selenium IDs to be unique, so it almost can't distinguish those pictures if you try to use find_element(By.ID) there.

The easiest way to resolve this problem is to totally ignore the ID and just fetch the <img> elements via XPath or CSS. For e.g. if all of them have the same ID but their src is different, you can just get them all like this:

images = driver.find_elements(By.XPATH, "//img[@id='Id']")
for img in images:
    print(img.get_attribute("src"))

You can also do the same using CSS:

images = driver.find_elements(By.CSS_SELECTOR, "img#Id")

In the end, you can get through all the list elements and perform any actions you want .

It works this way because find_elements returns all the elements that match, even if the HTML is somewhat broken (like duplicated IDs). So rather than depending on the ID, you're basically handling them as a regular list of elements.

Moreover, if you want to locate an image using its src, this would work most of the time:

for img in images:
    if "target_image.png" in img.get_attribute("src"):
        img.click()
        break

So, yeah - it's better to skip find_element(By.ID) here. Selenium assumes that IDs are unique, and if the page is not following the rules, XPath/CSS is just a safer way to work ​‍​‌‍​‍‌​‍​‌‍​‍‌with.

New contributor
Harshpreet Singh is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

1 Comment

The Node.js selenium-webdriver SDK uses *[id="$ID"] for By.id()
0

Since ids are meant to be unique in HTML, many searches by id will stop at the first match. In order to cope with this invalid HTML that you have to work with, a way to do so is to use an attribute selector for id, see here:

driver.findElements(By.cssSelector("[id='yourid']"));

Explanation:

  • driver.findElements searches for a plurality of elements matching the criteria given
  • By.cssSelector is treating the received parameter as a CSS selector to search by
  • [id='yourid'] is a CSS attribute selector, which looks for tags matching yourid in their id value

After getting the results, which are the matches, you can loop them and differentiate them within each iteration of your loop.

4 Comments

Why would you suggest using By.cssSelector("[id='yourid']") instead of the much simpler, easier to read By.id('yourid')??? This also doesn't solve the problem OP is having... which is how to distinguish between all the IMG tags with the same ID.
If you get all the images with the given id, then you can loop the result.
...and your answer doesn't address that.
I thought it was clear, nevertheless, edited my answer in order to clarify.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.