Home > Back-end >  Python Selenium find element with dynamic ID
Python Selenium find element with dynamic ID

Time:09-21

I designed a Python Script which scraps a website and fills in some details about users. This was pretty easy, as the website offered a specific ID for each of the elements I needed. Now, they've deployed an update which changed the interface and all text boxes have dynamic IDs (they are different between each one of them, and they change when the page is refreshed).

I tried searching for CSS Selector, doesn't work. The FULL XPATH is not useful because if they change the divs or something, nothing will work. I can't find them by text either... This is their page and HTML code

enter image description here enter image description here

I need to fill in the First Name/Last Name/Email, but as you can see they have the same TYPE, and the same CLASS, and their IDs are random, both starting with input.

I managed to find the first one, type in some text, then press X tabs to cycle through them.

browser.find_element_by_class_name('input').send_keys('MICHAEL')
actions.send_keys(Keys.TAB)
actions.perform()
actions.send_keys('FULKE')
actions.perform()

Is there any way I can point directly to specific text fields? I can't just cycle through them using TAB (maybe they change their position/order)...

Any help would be greatly appreciated

CodePudding user response:

<div class="form-field__label" data-v-78510568=""> First Name <!----></div><div class="form-field__control" data-v-78510568=""><input id="input_vlcbo61z5" type="text" class="input" data-v-728ea34e="" data-v-5890f98b=""></div><!----></div></div><div class="grid-item grid-item-xl-6" data-v-963e69fe="" data-v-5890f98b=""><div class="form-field" data-v-78510568="" data-v-5890f98b=""><div class="form-field__label" data-v-78510568=""> Website <!----></div><div class="form-field__control" data-v-78510568=""><input id="input_umpb7xvn9" type="text" class="input" placeholder="www.website.com" data-v-728ea34e="" data-v-5890f98b=""></div><!----></div></div><div class="grid-item grid-item-xl-6" data-v-963e69fe="" data-v-5890f98b=""><div class="form-field" data-v-78510568="" data-v-5890f98b=""><div class="form-field__label" data-v-78510568=""> Last Name <!----></div><div class="form-field__control" data-v-78510568=""><input id="input_g9tlbt7dt" type="text" class="input" data-v-728ea34e="" data-v-5890f98b=""></div><!----></div></div><div class="grid-item grid-item-xl-6" data-v-963e69fe="" data-v-5890f98b=""><div class="form-field" data-v-78510568="" data-v-5890f98b=""><div class="form-field__label" data-v-78510568=""> Phone <!----></div><div class="form-field__control" data-v-78510568=""><input id="input_sfurpm31l" type="text" class="input" data-v-728ea34e="" data-v-5890f98b=""></div><!----></div></div><div class="grid-item grid-item-xl-6" data-v-963e69fe="" data-v-5890f98b=""><div class="form-field" data-v-78510568="" data-v-5890f98b=""><div class="form-field__label" data-v-78510568=""> Email <!----></div><div class="form-field__control" data-v-78510568=""><input id="input_75ko5w3cw" type="text" class="input" data-v-728ea34e="" data-v-5890f98b=""></div><!----></div></div><div class="grid-item grid-item-xl-6" data-v-963e69fe="" data-v-5890f98b=""><div class="form-field" data-v-78510568="" data-v-5890f98b=""><div class="form-field__label" data-v-78510568=""> Fax <!----></div><div class="form-field__control" data-v-78510568=""><input id="input_noz2c1g4a" type="text" class="input" data-v-728ea34e="" data-v-5890f98b=""></div><!----></div></div><div class="grid-item grid-item-xl-6" data-v-963e69fe="" data-v-5890f98b=""><div class="form-field" data-v-78510568="" data-v-5890f98b=""><div class="form-field__label" data-v-78510568=""> Job Title <!----></div><div class="form-field__control" data-v-78510568=""><input id="input_w7p0iec5u" type="text" class="input" data-v-728ea34e="" data-v-5890f98b=""></div><!----></div></div></div><h2 class="text text_h2 user__add-subtitle" data-v-73655104="" data-v-5890f98b="">Groups</h2><div class="grid-container" data-v-963e69fe="" data-v-5890f98b=""><div class="grid-item grid-item-xl-6" data-v-963e69fe="" data-v-5890f98b=""><div class="form-field" data-v-78510568="" data-v-5890f98b=""><!----><div class="form-field__control" data-v-78510568=""><div class="input-tags" data-v-2af32715="" data-v-5890f98b=""><div class="input-tags__field" data-v-2af32715=""><input id="input-tags_folh9wox7" type="text" placeholder="" autocomplete="off" class="input-tags__control" data-v-2af32715=""></div></div></div><!----></div>

I found one way: using browser.find_elements_by_class_name and then use that list to grab [0], [2], [4] (which are FirstName/LastName/Email)... but yet again, it's bonkers?!

CodePudding user response:

There are many ways of doing this. The best way to work with dynamic ids is..... not working with dynamic ids. That's a requirement we often push when automating UI test cases.

However, there might be some that are dynamic. In those cases it's best to have stable locators that need little maintaniance.

How do we do that?

Patttern-matching specific attributes:

//div[contains(@text,'First Name')]/../div[contains(@class,'control')]/input

This selects the div that contains the matching text, goes up one element (necessary to match the text field for each specific element, assuming they follow a similar structure) and then matches the input inside the control.

Grouping all elements and looping by location in the page

You can grab all inputs, and loop through them :)

(//input)[0] # will select the first index (First Name), [1] second, etc.
  • Related