Hi how can I get an element by attribute and the attribute value in Python Selenium?
For example I have class="class1 class2 class3".
Now I want to get the element with the attribute class what ca.rries the classes "class1 class2 class3".
Is this possible?
If I use xpath, I always need to add the element type, input, option,...
I try to avoid the element type since it varies sometimes.
While constructing locators considering css-selectors or xpath you have to use the different attributes and the attribute-values to identify the WebElement uniquely within the DOM Tree.
The generic way is:
Using css_selector:
button.classname[attributeA='attributeA_value'][attributeB='attributeB_value']
Using xpath and attributes:
//button[#attributeA='attributeA_value'][#attributeB='attributeB_value']
As an example, for an element like:
<button type="button" aria-hidden="true" class="close alert alert-close" data-notify="dismiss">Close</button>
You can identify the Close element using either of it's the attributes and the corresponding attribute-values using either of the Locator Strategies:
Using css_selector:
button.close.alert.alert-close[data-notify='dismiss']
classes-> ^ ^^ ^^^ data-notify ^^^^ attribute
Using xpath and attributes:
//button[#class='close alert alert-close' and #data-notify='dismiss']
class attributes ^ ^^ ^^^ data-notify ^^^^ attribute
Using xpath and innerText:
//button[text()='Close']
innerText ^
The CSS selectors would be formatted like this:
'[attribute]'
'[attribute="value"]'
For example, the selector for the input field on google.com would be:
'input[name="q"]'
to answer this part
If I use xpath, I always need to add the element type, input,
option,... I try to avoid the element type since it varies sometimes.
you can use //* and then attribute type and attribute value.
//*[#class='class1 class2 class3']
//* represent any or all nodes
Related
I hope you're fine.
I'm scraping the logos of some websites. I'm using the next code to localize them. I don't use a tag only the * because the class or attribute that contains the substring 'logo' there is not always in a <div> or <a> tags.
driver.find_element(By.CSS_SELECTOR, "*[class*='logo']")
I have obtained some of them but in some cases the 'class' doesn't have the substring 'logo'. I've checked some websites and the logo has attributes like 'id', 'alt' or 'name' that contains the substring 'logo'.
So I want to know if is there some condition like OR to applied it and if there is no match with 'class' then check in 'id', etc.
I tried with these options but both launch an error:
driver.find_element(By.CSS_SELECTOR, "*[class*='logo'] | *[id*='logo']")
driver.find_element(By.CSS_SELECTOR, "*[class*='logo'] || *[id*='logo']")
In both cases the error is:
selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: An invalid or illegal selector was specified
You can use , to group multiple CSS selectors.
driver.find_element(By.CSS_SELECTOR, "[class*='logo'], [id*='logo']")
If you are not specific about using CSS_SELECTOR, you can try using XPATH as below:
//*[#*='logo']
Code should be:
driver.find_element(By.XPATH, "//*[#*='logo']")
This XPath expression will search the entire DOM(//*) for all attributes(#*) like class,id,name etc. which has the value =logo
Currently I have this line of code which correctly selects this type of object on the webpage I'm trying to manipulate with Selenium:
pointsObj = driver.find_elements(By.CLASS_NAME,'treeImg')
What I need to do is add in a partial string match condition as well which looks in the section "CLGV (AHU-01_ahu_ChilledWtrVlvOutVolts)" in the line below.
<span class="treeImg v65point" style="cursor:pointer;">CLGV (AHU-01_ahu_ChilledWtrVlvOutVolts)</span>
I found online there's the ChainedBy option but I can't think of how to reference that text in the span. Do I need to use XPath? I tried that for a second but I couldn't think of how to parse it.
Refering both the CLASS_NAME and the innerText you can use either of the following locator strategies:
xpath using the classname treeImg and partial innerText:
pointsObj = driver.find_elements(By.XPATH,"//span[contains(#class, 'treeImg') and contains(., 'AHU-01_ahu_ChilledWtrVlvOutVolts')]")
xpath using all the classnames and entire innerText:
pointsObj = driver.find_elements(By.XPATH,"//span[#class='treeImg v65point' and text()='CLGV (AHU-01_ahu_ChilledWtrVlvOutVolts)']")
ProductNames is an array of required data when using this line:
ProductNames[3].find_element_by_css_selector('.aok-align-bottom').get_attribute("innerHTML")
I'm getting this:
<span class="a-icon-alt">4.3 out of 5 stars</span>
So how can I extract only exactly text 4.3 out of 5 stars from span tag
You should include in your css_selector this >span too, and search get_attribute("innetHTML") on <span class="a-icon-alt">4.3 out of 5 stars</span>
Try something like this:
ProductNames[3].find_element_by_css_selector('.aok-align-bottom').get_attribute("innerHTML").text
You don't extract from innerHTML. Rather you extract text or the value of any attribute of a WebElement.
To extract the text _4.3 out of 5 stars_ you need to move one step deeper to the <span> and you can use the following Locator Strategy:
ProductNames[3].find_element_by_css_selector('.aok-align-bottom>span.a-icon-alt').get_attribute("innerHTML")
Or simply:
ProductNames[3].find_element_by_css_selector('.aok-align-bottom>span').get_attribute("innerHTML")
As an alternative, you can also use the text attribute as follows:
ProductNames[3].find_element_by_css_selector('.aok-align-bottom>span.a-icon-alt').text
Or simply:
ProductNames[3].find_element_by_css_selector('.aok-align-bottom>span').text
References
You can find a couple of relevant discussions in:
get_attribute() method Gets the given attribute or property of the element.
text attribute returns The text of the element.
Difference between text and innerHTML using Selenium
I look up the information that lxml does not support xpath2.0 so that it can't use ends-with, so selenium can't use ends-with how to use it or replace ends-with. thank you very much indeed!!!
HTML sample
<span id="xxxxx_close">wwwww</span>
The 'xxxxx' part of #id is random
You can apply an ends-with CSS selector:
By.cssSelector("[id$=_close]")
There's no need of including span tag in css selector search as well.
The ends-with XPath Constraint Function is part of XPath v2.0 but as per the current implementation Selenium supports XPath v1.0.
As per the HTML you have shared to identify the element you can use either of the Locator Strategies:
XPath using contains():
xpath using contains for id attribute:
driver.findElement(By.xpath("//span[contains(#id,'_close')]")).click();
xpath using contains for id and innerHTML attribute:
driver.findElement(By.xpath("//span[contains(#id,'_close') and contains(.,'wwwww')]")).click();
Alternatively, you can also use CssSelector as follows:
css_selector using ends-with (i.e. $ wildcard) clause for id attribute:
driver.find_element_by_css_selector("span[id$='_close']").click();
css_selector using contains (i.e. * wildcard) clause for id attribute:
driver.find_element_by_css_selector("span[id*='_close']").click();
I am trying to click on this element using python-selenium bindings .There are multiple elements with the same class but different data-original-title attribute .
How can I access these elements with data-original-title="Like" directly ?
instead of having to fetch first by class names then loop through elements for desired attribute .
HTML code
<div class="IconContainer js-tooltip" data-original-title="Like">
If you meant that the attribute data-original-title is always unique, you can select the element with the desired attribute value using xpath:
//div[#data-original-title='Like']