I'm using Selenium Python to locate label element.I want to use ::before to locate it,because this is a pop window.
<div class="crow" grp="0" grpname="Pizza Size">
::before
<label class="label0" cid="1">
<input type="radio" name="0" coname="M" sname="" price="9.99" value="392">M<b class="ip">9.99</b>
</label>
<label class="label0" cid="1"><input type="radio" name="0" coname="L" sname="" price="11.99" value="393">L<b class="ip">11.99</b>
</label><div style="clear:both">
</div>
</div>
I have no idea how to use ::before to locate it,any friend can help?
Pseudo Elements
A CSS pseudo-element is used to style specified parts of an element. It can be used to:
Style the first letter, or line, of an element
Insert content before, or after, the content of an element
::after
::after is a pseudo element which allows you to insert content onto a page from CSS (without it needing to be in the HTML). While the end result is not actually in the DOM, it appears on the page as if it is, and would essentially be like this:
CSS:
div::after {
content: "hi";
}
::before
::before is exactly the same only it inserts the content before any other content in the HTML instead of after. The only reasons to use one over the other are:
You want the generated content to come before the element content, positionally.
The ::after content is also "after" in source-order, so it will position on top of ::before if stacked on top of each other naturally.
Demonstration of extracting properties of pseudo-element
As per the discussion above you can't locate the ::before element within the DOM Tree but you can always be able to retrieve the contents of the pseudo-elements, i.e. ::before and ::after elements. Here's an example:
To demonstrate, we will be extracting the content of ::after element (snapshot below) within this website:
Code Block:
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("start-maximized")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=options, executable_path=r'C:\WebDrivers\chromedriver.exe')
driver.get('https://meyerweb.com/eric/css/tests/pseudos-inspector-test.html')
script = "return window.getComputedStyle(document.querySelector('body>p.el'),':after').getPropertyValue('content')"
print(driver.execute_script(script).strip())
Console Output:
" (fin.)"
This console output exactly matches the value of the content property of the ::after element as seen in the HTML DOM:
This usecase
To extract the value of the content property of the ::before element you can use the following solution:
script = "return window.getComputedStyle(document.querySelector('div.crow'),':before').getPropertyValue('content')"
print(driver.execute_script(script).strip())
Outro
A couple of relevant documentations:
Document.querySelector()
Window.getComputedStyle()
If I am not wrong, then, selenium doesn't provide any function or API call for this.
You can try parsing the html and then finding the tag using a simple regular expression.
Hope this helps :)
Related
My objective is to open a webpage, and click the app button for a specific app, like Anaplan. In the past, I've used get element by CSS selector with the combination of class, and ID, as shown in this past post.
first_item = driver.find_element_by_id("anaplan")
I've come across a webpage where the buttons seem to have literally no ID whatsoever, or unique values:
HTML output of the Anaplan App button:
<a
aria-label="launch app Anaplan"
class="chiclet a--no-decoration"
data-se="app-card"
href="https://gartner.okta.com/home/anaplan/0oaforg08lyATdLuw4x6/2487"
draggable="true"
><article class="chiclet--article">
<button
class="chiclet--action"
tabindex="0"
aria-label="Settings for Anaplan"
data-se="app-card-settings-button"
>
<svg
class="chiclet--action-kebab"
width="20"
height="4"
viewBox="0 0 20 4"
fill="#B7BCC0"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="2" cy="2" r="2"></circle>
<circle cx="10" cy="2" r="2"></circle>
<circle cx="18" cy="2" r="2"></circle>
</svg>
</button>
<section class="chiclet--main" data-se="app-card-main">
<img
class="chiclet--main-logo"
src="https://ok11static.oktacdn.com/fs/bcg/4/gfs1ev15ab63zqgZ91d8"
alt="Anaplan logo"
/>
</section>
<footer class="chiclet--footer" data-se="app-card-footer">
<o-tooltip content="Anaplan" position="bottom" class="hydrated"
><div slot="content"></div>
<div aria-describedby="o-tooltip-0">
<h1 class="chiclet--app-title" data-se="app-card-title">Anaplan</h1>
</div>
</o-tooltip>
</footer>
</article>
</a>
I grabbed the Xpath of the Anaplan button, which shows the following:
/html[#class='hydrated wf-proximanova-n4-inactive wf-
inactive']/body[#class='default']/div[#id='root']
/div[#class='enduser-app ']/section[#class='content-frame']
/main[#class='main-container has-top-bar']/div[#class='dashboard--main']/section[#id='main-
content']/section[#class='chiclet-area']
/section[#class='chiclet-grid--container']
/section/section[#class='chiclet-grid section-appear-done section-enter-done']
/a[#class='chiclet a--no-decoration'][1]/article[#class='chiclet--article']
The only differences between apps is the number in the bracket:
/a[#class='chiclet a--no-decoration'][1], where 1 seems to be Anaplan, 3 is G Drive, and so on. Is there a way to select elements such as this where there appears to be no unique identifier at all?
To locate the first button you can use one of the following xpaths //a[#aria-label='launch app Anaplan'] or //a[contains(#href,'anaplan')] and there are many other unique combinations. The same can be done with css selectors
Similarly to the above there are several combinations for all the other navigation buttons you provided here.
In case the element located inside <iframe> you have to switch to that <iframe> first and get out of it after that.
Locate the <iframe> with
iframe = driver.find_element_by_xpath("//iframe[#name='iframeName']") or whatever locator that it matches
Then switch_to the <iframe>:
driver.switch_to.frame(iframe)
If after that you need to continue anywhere out of the <iframe> switch out of it with
driver.switch_to.default_content()
It is possible both with xpath and css.
Example of xpath:
Anaplan:
//a[contains(#aria-label, 'Anaplan')]/article/button
Or:
//button[contains(#aria-label, 'Settings for Anaplan')]
Spam Quarantine:
//a[contains(#aria-label, 'Spam Quarantine')]
G-suite
//a[contains(#aria-label, 'G Suite Drive')]
The main idea is that you can find an element by writing a partial name of an attribute.
Update:
If an element is located inside an iframe, you should wait for it to load and switch to it. Selenium has very convenient method for it: frame_to_be_available_and_switch_to_it
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
driver = webdriver.Chrome()
driver.get(url)
wait = WebDriverWait(driver, 15)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe[data-testid=shell-content]")))
After switching to iframe you work with elements inside it.
This is my HTML code. I am using selenium.
<button class= "message-anywhere-button mn-connection-card__message-btn button-secondary-medium" aria-label="hello" data-ember-action="" data-ember-action-62="62">
<span aria-hidden="true"> Msg</span>
<span class="visually-hidden"> hello</span>
I have a list of more buttons like this one, and I need to get the number of the "Msg" Buttons.
driver = webdriver.Firefox()
message=drive.find_element_by_WHAT? (I tried id, class,css selector,but no one worked..)
If the same classname is present more than once.Try using find_elements and then count the length.
print(len(driver.find_elements_by_css_selector(".button-secondary-medium")))
Or try with area-lable if it is exists more than once.
print(len(driver.find_elements_by_xpath("//button[#aria-label='hello']")))
I have the following HTML page. I want to get all the links inside a specific div. Here is my HTML code:
<div class="rec_view">
<a href='www.xyz.com/firstlink.html'>
<img src='imga.png'>
</a>
<a href='www.xyz.com/seclink.html'>
<img src='imgb.png'>
</a>
<a href='www.xyz.com/thrdlink.html'>
<img src='imgc.png'>
</a>
</div>
I want to get all the links that are present on the rec_view div. So those links that I want are,
www.xyz.com/firstlink.html
www.xyz.com/seclink.html
www.xyz.com/thrdlink.html
Here is the Python code which I tried with
from selenium import webdriver;
webpage = r"https://www.testurl.com/page/123/"
driver = webdriver.Chrome("C:\chromedriver_win32\chromedriver.exe")
driver.get(webpage)
element = driver.find_element_by_css_selector("div[class='rec_view']>a")
link = element.get_attribute("href")
print(link)
How can I get those links using selenium on Python?
As per the HTML you have shared to get the list of all the links that are present on the rec_view div you can use the following code block :
from selenium import webdriver
driver = webdriver.Chrome(executable_path=r'C:\chromedriver_win32\chromedriver.exe')
driver.get('https://www.testurl.com/page/123/')
elements = driver.find_elements_by_css_selector("div.rec_view a")
for element in elements:
print(element.get_attribute("href"))
Note : As you need to collect all the href attributes from the div tag so instead of find_element_* you need to use find_elements_*. Additionally, > refers to immediate <a> child node where as you need to traverse all the <a> child nodes so the desired css_selector will be div.rec_view a
HTML information is :
<a title="Create an Account" class="button" href="http://demo.magentocommerce.com/customer/account/create/">
<span>
<span>Create an Account
</span>
</span>
</a>
Create an Account
I am trying with :
create_account_button = driver.find_element_by_xpath("//button[#title='Create an Account']")
create_account_button.click()
but it is not working
Actually assign the WebElement variable, u use the following code
WebElement button = driver.findElement(By.xpath("//a[#title='Create an Account']");
button.click();
Steps
Creating a WebElement variable button and assigning the value to it.
Performing click() on that webelement
For Java follow above steps, for Python use below
driver.find_element_by_xpath('//a[#title='Create an Account']').click()
Xpath you need To use be in <a> not in <button>
So try this Xpath //a[#title='Create an Account']
This HTML block:
<td class="tl-cell tl-popularity" data-tooltip="9,043,725 plays" data-tooltip-instant="">
<div class="pop-meter">
<div class="pop-meter-background"></div>
<div class="pop-meter-overlay" style="width: 57%"></div>
</div>
</td>
equates to this XPath:
xpath = '//*[#id="album-tracks"]/table/tbody/tr[5]/td[6]'
Trying to extract the text: 9,043,725 plays with
find_element_by_xpath(xpath).text()
returns an empty string. This text is only generated when a user hovers their mouse over the HTML block.
Is there a way to alter the XPath so that an empty string is not returned but the actual string is returned?
Try using get_attribute instead. The intended element can be located using any find_elements mechanisms. See the API DOC
element = browser.find_elements_by_css_selector('.tl-cell.tl-popularity')
text = element.get_attribute('data-tooltip')