I am trying to grab an attribute of a child. I inspect my element in Chrome, and see the following code for it:
<div class="input-wrapper">
<ion-label style="text-overflow: ellipsis; display; block; overflow: hidden;white-space: nowrap;" class="label label-md" id="lbl-80" producttypeid="39553">Item 1</ion-label>
The attribute that I need is "producttypeid".
When I right click on the first row and choose its selector the following command gives me nothing:
browser.find_element_by_css_selector("cssFromChrome").get_attribute("producttypeid")
When I right click on the second row and choose its selector, the selector that I get is #lbl-80 which is not good for me since it is dynamic, and I need something static to grab that element.
What else can I try to grab that attribute?
One of the options is regex match if id will always uniquely start with lbl-
browser.find_element_by_css_selector("ion-label[id^='lbl-']").get_attribute("producttypeid")
Another option is to use the child
browser.find_element_by_css_selector(".input-wrapper > ion-label").get_attribute("producttypeid")
As per the HTML if you want to extract the producttypeid attribute of the child you can write a function as follows :
def get_producttypeid(myString):
print(driver.find_elements_by_xpath("//div[#class='producttypeid']/ion-label[#class='label label-md' and starts-with(#id,'lbl-')][.='" + myString + "']").get_attribute("producttypeid"))
Now, from you can call the get_producttypeid() method with the required item description e.g. Item 1 to retrieve the producttypeid attribute as follows :
get_producttypeid("Item 1");
How about:
element = browser.find_element_by_xpath("//*[contains(#id, 'lbl') and contains(text(), 'Item 1')]").get_attribute("producttypeid")
Related
I'm playing around with booking.com as I teach myself selenium / python. I'm trying to select a currency based on a known string e.g. 'USD'.
I'm able to click the currency icon to open the currency selection modal but then when I try to say find element where text = 'USD', I get:
selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: An invalid or illegal selector was specified
1. Here is the list item for 'USD':
<li class="ccff2b4c43 ea27cffb06"><button data-testid="selection-item" type="button" class="fc63351294 ea925ef36a bf97d4018a ae8177da1f cddb75f1fd"><div class="a1b3f50dcd a1f3ecff04 b2fe1a41c3 db7f07f643 d19ba76520"><div class="b1e6dd8416 aacd9d0b0a"><span class="cf67405157">U.S. Dollar<div class=" ea1163d21f">USD</div></span></div><div class=""></div></div></button></li>
2. Here is my known string I'm trying to search for:
currency = 'USD'
3. Here is my attempt at trying to find (then select) this string in the HTML:
selected_currency_element = self.find_element(By.CSS_SELECTOR, f'//span[text()={currency}]')
selected_currency_element.click()
I assume I don't need to read this modal's entire unordered list into an array then loop through it to find the string? Or do I?
Couple of things to rectify.
The used syntax is for XPATH and you have used CSS_SELECTOR need to change to XPATH
selected_currency_element = self.find_element(By.XPATH, f'//span[text()={currency}]')
If you see the node USD is inside a DIV tag of parent SPAN
So your xpath should be like
selected_currency_element = self.find_element(By.XPATH, f'//span[.//div[text()="{currency}"]]')
Instead of using the abbreviation, I used the long name. This works pretty good. By the way, I use Firefox as my browser
from selenium.webdriver.common.by import By
from selenium import webdriver
def change_currenecy(country):
dvr = webdriver.Firefox()
dvr.get("https://www.booking.com/")
dvr.find_elements(By.XPATH, "//span[contains(text(),'USD')]")[0].click()
dvr.find_elements(By.XPATH, f"//span[contains(text(),'{country}')]")[0].click()
change_currenecy("Thai Baht")
You need to take care of a couple of things here:
Though you mentioed By.CSS_SELECTOR but the value is of a xpath. So you need to change the locator strategy as:
selected_currency_element = self.find_element(By.XPATH, f'xpath_value')
The desired text USD is within the descendant <div> of it's parent <span>, so you need to go a step deeper.
Solution
Your effective line of code will be:
currency = 'USD'
selected_currency_element = self.find_element(By.XPATH, f'//span//div[text()={currency}]')
selected_currency_element.click()
I'm trying to get text using Selenium WebDriver and here is my code. Please note that I don't want to use XPath, because in my case the ID gets changed on every relaunch of the web page.
My code:
driver.find_element_by_class_name("05uR6d").text
HTML:
<div class="O5uR6d">to fasten stuff</div>
Error:
selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: An invalid or illegal selector was specified (Session info: chrome=88.0.4324.150)
Error is specific to the line of code I mentioned above.
How can I fix this?
Use this xpath:
driver.find_element_by_xpath("//div[contains(text(),'to fasten stuff')]")
Or this CSS:
driver.find_element_by_css_selector(".O5uR6d")
If both won't work, improve your question by adding more data of HTML you are looking at.
It can be done using multiple ways let me try to explain most of them.
Get element by class name.
this is the most easiest solution to get any element by class name you can simply do is:
driver.find_element_by_class_selector('foo');
Get Element by xpath
This is a bit tricky one, you can apply xpath either the class name, title, id or whatever remains same. it also works even if there's a text inside your div. For example:
driver.find_element_by_xpath("//tagname[#attribute='value']")
or in your case:
driver.find_element_by_xpath("//div['class='O5uR6d']")
or you can do something like #vitaliis said
driver.find_element_by_xpath("//div[contains(text(),'to fasten stuff')]")
You can read more about xpath and how to find it on this link
Get Elements by ID:
You can also get the element from id if there's any that's static:
driver.find_element_by_id('baz')
Get Elements by Name:
Get Elements by name using the following syntax:
driver.find_element_by_name('bazz')
Using CSS Selectors:
You can also use the css selectors to find the elements. Consider a following tag that has some attributes:
<p class="content">Site content goes here.</p>
You can get this element by:
driver.find_element_by_css_selector('p.content')
You can read more about it over here
I have a webpage with the following:
<span class="plugin_pagetree_children_span plugin_pagetree_current" id="childrenspan173273808-0"> Shift Turnover </span>
and I can successfully find it by link text using st = driver.find_element_by_link_text('Shift Turnover')
but when I print the id using print('-',st.id)
The id prints out as 63cd644e-495b-4985-8f9e-7ea067a2b6f1 instead of childrenspan173273808-0.
I've also attempted to get_attribute and get_property but those aren't working either. Any hints/tips/suggestions welcomed.
Thanks in advance.
The issue I'm seeing here is that you are trying to get the ID childrenspan173273808-0, but your selector driver.find_element_by_link_text('Shift Turnover') is locating the a element, which has no ID. That is why get_attribute is not working for you. You actually want to find the span element, which contains your desired ID.
You can use this to get the ID childrenspan173273808-0:
st = driver.find_element_by_xpath("//span[a[text()='Shift Turnover']]") # locate the span
id = st.get_attribute("id") # get its ID and print
print(id)
This XPath locates the span element that appears outside of the a element with text Shift Turnover. We query on the span which contains a element with Shift Turnover text, then call get_attribute on the span element, to retrieve your desired childrenspan173273808-0 ID.
Lastly -- the ID 63cd644e-495b-4985-8f9e-7ea067a2b6f1 that was printing out in your example was not the WebElement ID attribute, but rather, "the server-assigned opaque ID for the underlying DOM element". This is detailed in the Selenium docs on WebElement.
You are trying to retrieve value of web element. You need to use get_attribute method which is declared inside the Web element interface. Basically this method will return the value of the specified attribute in the string format.
Solution 1:
locator= driver.find_element_by_xpath("//span[#id='childrenspan173273808']//a").get_attribute("id")
print(locator)
Solution 2:
locator=driver.find_element_by_xpath("//span[#class='plugin_pagetree_children_span plugin_pagetree_current']//a[1]").get_attribute("id")
print(locator)
I have a xpath as:
//*[#id="jobs-search-box-keyword-id-ember968"]
The number 968 constantly keeps on changing after every reload.
Rest of the string remains constant.
How to I find the constantly changing xpath?
You can use partial id with contains()
//*[contains(#id, "jobs-search-box-keyword-id-ember")]
You can try using starts-with below,
//*[starts-with(#id,'jobs-search-box-keyword-id-ember')]
The details provided is insufficient to to provide the accurate result. Still you can follow the below code references
In //*[#id="jobs-search-box-keyword-id-ember968"] the last number 968 keeps changing. but if you make this like //*[starts-with(#id,'jobs-search-box-keyword-id-ember')] then there might be possibility that you can have more then one element with the same partial is i.e. jobs-search-box-keyword-id-ember in this case it will locate on 1st matching element. that may not be your expected one
Use the tag name lets say element is an input tag whose id is jobs-search-box-keyword-id-ember968
Xpath - //input[starts-with(#id,'jobs-search-box-keyword-id-ember')]
CSS - input[id^='jobs-search-box-keyword-id-ember']
Use the relevant parent element to make this more specific. e.g the element is in parent tag <div class="container">
Xpath- //div[#class='container']//input[starts-with(#id,'jobs-search-box-keyword-id-ember')]
CSS - div.container input[id^='jobs-search-box-keyword-id-ember']
This worked for me:
Locator:
JOBS_SEARCH_BOX_XPATH = "//*[contains(#id,'jobs-search-box-keyword-id-ember')]"
Code:
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, JOBS_SEARCH_BOX_XPATH)))
.send_keys("SDET")
I am attempting to locate a user name field that does not have an ID or other locator that I can easily find using Selenium Web Driver.
Using Chrome's Inspect Element, the HTML for this object is as follows
<div aria-hidden="true" style="cursor:text" data-bind="text: hintText, css: hintCss" class="placeholder">someone#example.com</div>
What would be the best way to locate this page object?
Thanks
Either of these should work (if it is the first div-element of this class type)
driver.find_element_by_class_name('placeholder')
driver.find_element_by_css_selector('div.placeholder')
driver.find_element_by_xpath("//div[#class='placeholder']")
If there are more elements which match use the find_elements version of the methods and use the index of the returned list the get the element you need.
To click() the User Name field you can use either of the following line of code :
Using class and text attributes :
driver.findElement(By.xpath("//div[#class='placeholder' and contains(text(),'someone#example.com')]"));
Using class and aria-hidden attributes :
driver.findElement(By.xpath("//div[#class='placeholder' and #aria-hidden='true']"));
First find out is your element is inside different frame. Find the iframe, first switch to that, after which you will able to locate your user desired object by using any method like find_elemet_by_class_name or find_element_by_css_selector or by xpath.
For switching to frame try below code:
driver.switch_to.frame(driver.find_element_by_id("ID_OF_YOUR_FRAME"))
You can take the reference from this link code also for searching elements:
"https://github.com/PrajinkyaPimpalghare/TimeSheet-Automation/blob/master/time_sheet_automation.py" Refer from line 94 to 108 for accessing elements in different way and also in different frame.