Hi I can't figure out how to get an element by CSS and matching with text. I know it can be done with Xpath but I'd rather use CSS.
<div class="button-face">
<div class="button-face-caption"> Text I want to find 1</div>
</div>
<div class="button-face">
<div class="button-face-caption"> Text I want to find 2</div>
</div>
So in by CSS would be something like...
driver.find_element_by_css('div.button-face-caption')
But how can add the text matching to that? i tried with contains and innerText and none seem to work.
As you said it's supported in xpath:
This would be a solution with an xpath using contains and text()
driver.find_element_by_xpath('//div[#class="button-face-caption" and contains(text(),"Text I want to find")]')
The xpath being:
//div[#class="button-face-caption" and contains(text(),"Text I want to find")]
For css, look here: https://sqa.stackexchange.com/q/362/34209 which should allow us to use:
div:contains('Text I want to find')
Which would lead us to
driver.find_element_by_css("div:contains('Text I want to find')")
However this comes with a BIG caveat:
:contains() is not part of the current CSS3 specification so it will
not work on all browsers, only ones that implemented it before it was
pulled. (see w3.org/TR/css3-selectors)
As workaround you can create your own function
def find_by_css(selector, text=''):
return [element for element in driver.find_elements_by_css_selector(selector) if text in element.text][0]
Then you can call it as
find_by_css('div.button-face-caption') # search only by CSS-selector
or
find_by_css('div.button-face-caption', 'Text I want to find 2') # search by CSS + text
As per the following discussions:
CSS selector :contains doesn't work with Selenium
css pseudo-class :contains() no longer allows anchors
The :contains pseudo-class isn't in the CSS Spec and is not supported by either Firefox or Chrome (even outside WebDriver).
Solution
You need to consider the ancestor of the <div class="button-face"> element and traverse down. Let us assume that both the <div class="button-face"> are with in a parent <div class="class">:
<div class="class">
<div class="button-face">
<div class="button-face-caption"> Text I want to find 1</div>
</div>
<div class="button-face">
<div class="button-face-caption"> Text I want to find 2</>
</div>
</div>
So to identify the element with text as:
Text I want to find 1:
div.class div:first-child > div.button-face-caption
Text I want to find 2:
div.class div:nth-child(2) > div.button-face-caption
References
You can find a couple of relevant detailed discussions in:
selenium.common.exceptions.InvalidSelectorException with “span:contains('string')”
Finding link using text in CSS Selector is not working
Related
I'm looking to get the text "Interesting" which is the first occurrence of the class b after h1.important.
How would I do that in Selenium?
<div class="a">
<div class="b">Not interesting</div>
</div>
<div class="title">
<h1 class="important">Title</h1>
</div>
<div class="a">
<div class="b">Interesting</div>
</div>
Is there a way to find "Interesting" using a fancy selector or xpath?
This would also match the first element: driver.find_elements_by_css_selector(".b").text
driver.find_elements_by_css_selector(".b")
this will return a list in Python-Selenium bindings. so you cannot do .text on it.
Instead try to use driver.find_element like below :
driver.find_element_by_css_selector("div.title+div>.b").text
in case you want to use xpath, try this :
driver.find_element_by_xpath("//div[#class='title']/following-sibling::div/div").text
Note that, CSS_SELECTOR is preferred over xpath in Selenium automation.
This XPath
//h1[#class='important']/../following-sibling::*//*[#class='b']
Should give you the next b class occurrence after the h1.important node as you asking
This xpath should work
(//h1[#class="important"]/following::*[#class='b'])[1]
I need help with finding an exact element and click it with following-sibling based on specific id number and then classes and a (href or class).
Here is simplified code, the below example occurs many times just with different id:
<div class="class_1" id="1234567">
<div class="class_2">
<div class="class_3">
<div class="class_3.1">
<div class="class_3.2">
<div class="class_3.3">
<div class="class_3.3.1">
<div class="class_3.3.1.1">
<div class="class_3.3.1.2">
<div class="class_3.3.1.3">
...
How can I locate an element with id and class for example something like this and click on it:
driver.find_element(By.XPATH, 'class=class_1 and id="2222222" and class="event-media-icon live-icon icon-white').click()
The xpath you are looking for will look like the following:
//div[#class='class_1' and(#id='1234567')]//a[#data-sport='soccer']
I guess the elements between the upper div and the goal a are not important so we can omit them.
The href value looks not unique too so I preferred using data-sport attribute that can be more unique.
To give more precise answer I need to see that web page with dev tools.
This xpath should work fine too
.//div[#class='class_1' and #id='1234567']//following-sibling::a[#data-sport='soccer']
I'm working with Python Selenium, and in the following HTML structure:
<div>
<h2>Welcome</h2>
<div>
<p>some text <strong>important</strong></p>
<a>link</a>
</div>
</div>
I'd like to get the text from each descendant (h2, div, p, strong, a) of the parent div, e.g. for the <p> tag I want some text.
I've been using the .text attribute and getting some text important instead. I'd like to use something similar as the BeautifulSoup attribute .string.
Edit: I need the code to work for any parent element containing descendants with more nested descendants - not just this particular HTML structure.
Thanks for your help.
Use Java Script executor to return textContent.
print(driver.execute_script('return arguments[0].firstChild.textContent;', driver.find_element_by_xpath("//h2[contains(.,'Welcome')]/following::div/p")))
<div id="tabs" class="clearfix">
<ul id="remove">
<li class="btn_arrow_tab left inactive">
<a href="#" class="doubleText">Pay Monthly <small>View standard rates and Bolt Ons</small>
</a>
</li>
<li class="btn_arrow_tab right inactive">
<a href="#" class="doubleText">Pay & Go<small>View standard rates and Bolt Ons</small>
</a>
</li>
</ul>
</div>
I have no experience in webscraping and trying to follow example and the docs to click on the button with text 'Pay Monthly'. This button then dynamically displays some text which I need to copy. How do I go about clicking this for starters, and then reading the text which is displayed. I am trying it with Selenium, would beautifulsoup be better? I have been trying this line of code but it isn't doing anything:
driver.find_element_by_xpath("//a[text()[contains(.,'Pay Monthly')]]").click()
It is always good practice to use mixture of absolute and relative xpath to locate a element.
First thing you should find is a parent that has a unique identifier. The element you mentioned has two parent items with a static id. One is root div and another is ul.
Now either we can follow your path and find the element using Text. Any of the following shall work.
driver.find_element_by_xpath("//div[#id='tabs']//a[text()[contains(.,'Pay Monthly')]]").click()
driver.find_element_by_xpath("//ul[#id='remove']//a[text()[contains(.,'Pay Monthly')]]").click()
But, if the item is static element and considering your goal here, I would suggest the following method. indexing your xpath when it returns multiple elements.
myElement = driver.find_element_by_xpath("//div[#id='tabs']//a[#href='#'][1]")
myElement.click()
And then you can capture the text. You can put some wait to ensure the text gets changed.
myText = myElement.text
Let me know if this doesn't work.
I am using Python & Selenium to scrap the content of a certain webpage. Currently, I have the following problem: There are multiple div-classes with the same name, but each div-class has different content. I only need the information for one particular div-class. In the following example, I would need the information in the first "show_result"-class since there is the "Important-Element" within the link text:
<div class="show_result">
<a href="?submitaction=showMoreid=77" title="Go-here">
<span class="new">Important-Element</span></a>
Other text, links, etc within the class...
</div>
<div class="show_result">
<a href="?submitaction=showMoreid=78" title="Go-here">
<span class="new">Not-Important-Element</span></a>
Other text, links, etc within the class...
</div>
<div class="show_result">
<a href="?submitaction=showMoreid=79" title="Go-here">
<span class="new">Not-Important-Element</span></a>
Other text, links, etc within the class...
</div>
With the following code I can get the "Important-Element" and its link:
driver.find_element_by_partial_link_text('Important-Element'). However, I also need the other information within the same div-class "show-result". How can I refer to the entire div-class that contains the Important-Element in the link text? driver.find_elements_by_class_name('show_result') does not work since I do not know in which of the div-classes the Important-Element is located.
Thanks,
Finn
Edit / Update: Ups, I found the solution on my own using xpath:
driver.find_element_by_xpath("//div[contains(#class, 'show_result') and contains(., 'Important-Element')]")
I know you've found an answer but I believe it's wrong since you would also select the other nodes because Important-Element is still in Non-Important-Element.
Maybe it works for your specific case since that's not really the text you're after. But here are a few more answers:
//div[#class='show_result' and starts-with(.,'Important-Element')]
//div[span[text()='Important-Element']]
//div[contains(span/text(),'Important-Element') and not(contains(span/text(),'Non'))]
There are more ways to write this...
Ups, i found the solution on my own via xpath:
driver.find_element_by_xpath("//div[contains(#class, 'show_result') and contains(., 'Important-Element')]")