How can I get random ID of element? - python

I have a situation, the id always change for a random one,
so I can't use find_element_by_id
have some divs above,
<div class="x-tree-view x-fit-item x-tree-view-default x-unselectable"
id="treeview-2234"
tabindex="0"
componentid="componentstree-1118"
style="overflow: auto;
margin: 0px; height: 443px; width: 228px;">
<div class="x-grid-item-container"
style="width: 228px;
transform:
translate3d(0px, 0px, 0px);">
<table id="treeview-2234-record-879"
data-boundview="treeview-2234"
data-recordid="879"
data-recordindex="0"
class="x-grid-item x-grid-item-selected"
cellpadding="0"
cellspacing="0"
style="width:100%;">
I already tried:
Use recordid, but sometimes the recordid repeats.
By class_name, but sometimes the class repeats.
OF course by id, but as I've already said, when page refreshes, it becomes another id
By treeview-2234 root...fail
I'm another victim of EXt, what can I do?

If the ID is different each time the page is refreshed then it is impossible to select the element by ID. Instead, you need to find a way to select the element by something else which is unique. This could be by using one of the attributes (data-boundview, data-recordid,....), or by selecting the path to the table element via the HTML structure which is loaded whenever the page is refreshed.
I would then use driver.find_element_by_xpath() to select the element. For example, you could select the element by attribute as follows:
driver.find_element_by_xpath('//table[#data-boundview="treeview-2234"]')
Alternatively, if you know the HTML structure, you could do something along the following lines:
driver.find_element_by_xpath('//div[#id="ancestor-div"]/div[#id="parent-div"]/table')

I would try xpath on the dom as expected. You may need to grab the not changing parent dom of the changing dom and get inside child from it by many ways esp in xpath-
Use contains function-
driver.find_element_by_xpath("//div[#class= 'x-grid-item-container']/table[contains(#data-boundview,'treeview-')]")
It will grab all data-boundview that has value starts with treeview- If there are more data-boundview with value starts with treeview- then try to grab non-changing parent first and then dig into it to get child as i mentioned earlier.

if ur id changes randomly, use the unchanged classes, like below:
driver.find_element_by_css_selector("div.x-tree-view.x-fit-item.x-tree-view-default.x-unselectable");
this will select the first div.To choose second div, use
driver.find_element_by_css_selector("div.x-grid-item-container");
if the table is under this div, try like this:
driver.find_element_by_css_selector("div.x-grid-item-container>table.x-grid-item.x-grid-item-selected");

If id="treeview-2234" is constant in your id, you can search for id which contains it:
driver.find_element_by_css_selector('[id*="treeview-2234"]');

Related

How do I click on this item using Selenium?

Im trying to automate the download of report using selenium. To get to the page where the report is I have to click on an image with this code
<div class="leaflet-marker-icon single-icon-container running hover asset leaflet-zoom-hide leaflet-clickable" tabindex="0" style="margin-left: -22px; margin-top: -41px; width: 44px; height: 44px; opacity: 1; transform: translate3d(525px, 238px, 0px); z-index: 238;"><div class="icon-value" lid="219058"></div></div>
I tried with
wtg = driver.find_elements_by_class_name(
"leaflet-marker-icon single-icon-container running hover asset leaflet-zoom-hide leaflet-clickable")
wtg.click()
but nothing happens.
There are 7 elements with the same class, and a unique "id " tha looks like lid="219058" but I dont know how to select that.
leaflet-marker-icon single-icon-container running hover asset leaflet-zoom-hide leaflet-clickable contains multiple class names while driver.find_element_by_class_name method intends to get a single class name.
I can't give you a correct locator for this element since you didn't share the page link, however if you wish to locate that element based on these class names combination you can use CSS Selector or XPath as following:
wtg = driver.find_element_by_css_selector(".leaflet-marker-icon.single-icon-container.running.hover.asset.leaflet-zoom-hide.leaflet-clickable")
wtg.click()
Or
wtg = driver.find_element_by_xpath("//*[#class='leaflet-marker-icon single-icon-container running hover asset leaflet-zoom-hide leaflet-clickable']")
wtg.click()
Also you should use driver.find_element_by_class_name, not driver.find_elements_by_class_name since driver.find_elements_by_class_name will give you a list of web elements, not a single web element that can be clicked directly.
Alternatively you can use the first index inside the list of received web elements as described by FLAK-ZOSO
Generally speaking, the best practice when building web scrapers is to always use xpath, since xpath can apply all the filters (id, class, etc) in a more flexible way (in some cases though, performance in selenium might be decreased).
I recommend you check this article on how to write xpaths for various needs: https://www.softwaretestinghelp.com/xpath-writing-cheat-sheet-tutorial-examples/
For your particular use case, I would use:
driver.find_element_by_xpath('//div[#lid="219058"]')
This will actually click on the inner div (notice how the lid is actually inside the nested div). If you wish to click on the outer div you can use:
driver.find_element_by_xpath('//div[#lid="219058"]/parent::div')
I again recommend you to learn Xpath syntax and always use it, it is way easier to manipulate than the other selenium selectors and is also faster in case you ever choose to implement a C compiled html parser such as lxml to parse the elements.
Remember that driver.find_elements_by_class_name() returns a list.
You have to do something like this when using this get/find method:
driver.find_elements_by_class_name('class')[0] #If you want the first of the page
In your case you need to use the css_selector because you have multiple classes, like suggested by #Prophet.
You can also use only one of the classes and simply use the class_name selector.
In your case, if you need the first element of the page with that class, you have to add [0].

I can't get element by class

I am working with element like
<div class="slick-track" style="opacity: 1; width: 9140px; left: 0px;" role="listbox">
when trying to start using Robot Framework for Python for creating autotests
I need to check this element exist, and, its items. How can I do that?
You can simply use:
Page should contain element css=div.slick-track
Or even better, in order to avoid possible delay issues (like an element taking a few seconds to be displayed on the page)
Wait until page contains element css=div.slick-track
Comment: Didn't quite understand what you meant by "and, its items".
If i understood your question properly..
To locate the element by class:
Location should contain class:slick-track
to check its attributes:
element attribute value should be class:slick-track role listbox
let me know if this is what you meant.

to get xpath in python selenium for ID and class together

In python selenium, how to create xpath for below code which needs only id and class:
<button type="button" id="ext-gen756" class=" x-btn-text">Save</button>
And I also need to select Global ID from below drop-down without clicking it.
<div class="x-combo-list-item">Global ID</div>
My below solution is not working-
//div[#class='x-combo-list-item']/div[contains(.,'Global ID')]
I do not want to mention droplist sequence number like-
//div[#class='x-combo-list-item']/div[1]
If you want to club id and class together in your xpath try like this-
driver.find_element_by_xpath('//button[#id="ext-gen756"][#class=" x-btn-text"]');
You can also try the same using AND -
driver.find_element_by_xpath('//button[#id="ext-gen756" and #class=" x-btn-text"]');
EDITED
Your xpath seem incorrect. Use following -
driver.find_element_by_xpath('//div[#class="x-combo-list-item"][contains(.,"Global ID")]');
Just answering my own question after a long time had a look on this. The Question was posted when I was new in xpath topics.
<button type="button" id="ext-gen756" class=" x-btn-text">Save</button>
in terms of id and class:
driver.find_element_by_xpath("//button[#id='ext-gen756'][#class=' x-btn-text']")
Also sometime if Id's are dynamic and changes for every reload of the page then you may try:
driver.find_element_by_xpath("//button[#type='Save'][contains(#id,'ext-gen')][#class=' x-btn-text']")
Here I have used #type and for the #id contains option as prefix(ext-gen) usually remains the same for the dynamic ID's

What is a unique identifier and how to use it to select?

I use Selenium and I am trying to automate a task on a website and in order to select an item I have to use this:
select = driver.find_element_by_*whatever*
However, all the whatevers like find_element_by_id, by name, by tag name etc. are either unavailable or are shared by several items. The only one that seems to be unique to each item is a "data-id" number but there isn't a find_element_by_data_id function as far as I know.
I can get a unique identifier which looks like this:
div.item:nth-child(453)
It seems to fit since it doesn't change when I reload the page and is unique to only one item.
How can I use this unique identifier to select the object? Alternatively, could you suggest a way of how I could select the desired item?
Here's the HTML pertaining to the object:
...
</div>
<div data-id="3817366931"
data-slot="secondary"
data-classes="pyro"
data-content="Level: 30<br/>"
data-appid="440"
class="item hoverable quality6 app440"
style="opacity:1;background-image:url(https://steamcdn-a.akamaihd.net/apps/440/icons/c_drg_manmelter.b76b87bda3242806c05a6201a4024a560269e805.png);"
data-title="Manmelter"
data-defindex="595">
</div>
<div data-id="3820690816"
data-slot="primary"
data-classes="pyro"
data-content="Level: 10<br/>"
data-appid="440"
class="item hoverable quality6 app440"
style="opacity:1;background-image:url(https://steamcdn-a.akamaihd.net/apps/440/icons/c_drg_phlogistinator.99b83086e28b2f85ed4c925ac5e3c6e123289aec.png);"
data-title="Phlogistinator"
data-defindex="594">
</div>
<div data-id="3819377317"
data-slot="primary"
data-classes="pyro"
data-content="Level: 10<br/>"
data-appid="440"
class="item hoverable quality6 app440"
style="opacity:1;background-image:url(https://steamcdn-a.akamaihd.net/apps/440/icons/c_drg_phlogistinator.99b83086e28b2f85ed4c925ac5e3c6e123289aec.png);"
data-title="Phlogistinator"
data-defindex="594">
So the items in the two bottom boxes are the same. The one at the top is different. Let's I would like a way to select the item in the second box.
I am not sure how easy it will be to automate the scenario based on the html structure like this. I would suggest you to talk to the devs to see if they can add some kind of ids to each parent div otherwise the selector will be too brittle. I also see the data-id attribute is unique in every case so that could be your best bet if you somehow know the ids beforehand. If you do not have any other options then css nth-child() function is the next most reliable mechanism. But, in that case you have to know the parent. nth-child() is well explained here
On the other hand, if the intention is to find the second data-slot you can use the following xpath:
//div[#data-slot='primary'][2]

How to find element on page with text which is dynamically changed using web driver?

I'm looking for way to find element which contain some exactly text, the problem is this text dynamically changes every time.
It looks like this:
<div class="some class" ng-class="{ 'ngSorted': !col.noSortVisible90 }">
<span ng-call-text class="ngbinding" style="cursor: defaulte;">some text and digits</span>
Where "some text and digits" element that I need.
Could somebody help me with this?
UPD: I have a lot elements with the same classes on page and also I know text phrase thet should be fount, I can provide this text to my code as parameter.
You can use the id attribute
<span ng-call-text id="snarfblat" class="ngbinding" style="cursor: defaulte;">some text and digits</span>
so you can access it within JavaScript with
document.getElementById("snarfblat");
Why don't you use Xpath or CSSSelector to reach to your target element, maybe on of its parent has a unique Id or a property, start from there and reach you destination i.e the concerned HTML tag with dynamic text

Categories

Resources