Selenium Xpath works sometimes, does not work the following time - selenium

I'm trying to make an application to automate job applying on linkedin with selenium.
When I find an xpath for an element on the webpage and tell my code to locate the element, it found it and clicked it with no issue.
However when I run the same exact code later on
alpha = driver.find_element_by_xpath("//*[#id='ember2350']/form/button")
I'm greeted with a no such element exception, why does this happen?
Edit:
Here's the HTML of the button I'm trying to get to
<button aria-expanded="false" aria-controls="linkedin-features-facet-values" class="search-s-facet__name-wrap search-s-facet__name-wrap--pill button-secondary-medium-muted" data-is-animating-click="true">
<div class="search-s-facet__name-wrap-container search-s-facet__name-wrap-container--pill">
<div class="search-s-facet__name">
<span class="visually-hidden">Expand LinkedIn Features facet</span>
<h3 class="search-s-facet__name Sans-17px-black-55%-semibold">LinkedIn Features</h3>
</div>
<span class="search-s-facet__svg-icon svg-icon-wrap"><li-icon aria-hidden="true" type="caret-filled-down-icon" size="small"><svg viewBox="0 0 24 24" width="24px" height="24px" x="0" y="0" preserveAspectRatio="xMinYMin meet" class="artdeco-icon" focusable="false"><path d="M8.8,10.66L14,5.12A0.07,0.07,0,0,0,13.93,5H2.07A0.07,0.07,0,0,0,2,5.12L7.2,10.66A1.1,1.1,0,0,0,8.8,10.66Z" class="small-icon" style="fill-opacity: 1"></path></svg></li-icon></span>
</div>
</button>

On LinkedIn #id are dynamic values, so you shouldn't use them to locate elements. Try below instead:
driver.find_element_by_xpath("//button[.//span='Expand LinkedIn Features facet']").click()

It seems that the Id - "ember2350" is dynamic and the numeric is changing so that's why it is not working as it is changing everytime.
Use this xpath :
//span[normalize-space()='Easy Apply']

Related

How to click on the element using Selenium and VB.Net

Html of the element:
<div _ngcontent-nxg-c15="" class="box-shadow"><!----><a _ngcontent-nxg-c15="" class="clearfix con-card-voucher text-center ng-star-inserted" style="background-image: url("https://api.duniagames.co.id/api/product/upload/image/9231439531578882989.jpg");" href="/top-up/item/freefire"><!----><img _ngcontent-nxg-c15="" alt="Item Logo" class="icon-image style2" onerror="this.onerror=null;this.src='./assets/images/primary-logo.jpg';" src="https://api.duniagames.co.id/api/product/upload/image/13838880871566571420.jpg"><div _ngcontent-nxg-c15="" class="right style2"><h5 _ngcontent-nxg-c15="" class="title"><b _ngcontent-nxg-c15="">FreeFire</b></h5></div></a><!----></div>
The coding I used before was like this, but failed
Driver.FindElement(By.LinkText("FreeFire")).Click()
how to code properly
I use VB.Net
The desired element is an Angular element you need to induce some wait and you can use either of the following Locator Strategies:
Using FindElementByCss:
Driver.wait 3000
Driver.FindElementByCss("div.box-shadow a[href='/top-up/item/freefire'] h5.title>b").Click
Using FindElementByXPath:
Driver.wait 3000
Driver.FindElementByXPath("//h5[#class='title']/b[text()='FreeFire']").Click
Reference
You can find a relevant discussion in:
selenium whatsapp button search vba

selenium webdriver : How to click on particular button having classes applied to each. Unable to find exact x-path

Q. Same kind of class applied to all Download button,How to distinct them from each other? Let's say i want to click on 3rd number of download button. Find a xpath for that button.
I have tried this but it's common for all.
//div[#class='statement-download']
<div class="statement-download">
<button class="btn btn-sm btn-icon btn-outline btn-default mb-0" type="button">
<i class="mdi mdi-download m-r-5"></i>
<span>Download</span>
</button>
</div>
use the index of the parent div.
//div[#class='statement-card'][3]/div[#class='statement-download']
For 3rd, try following xpath:
(//div[#class='statement-download'])[3]
You can use the date as a starting point
date = 'July 2048'
//div[.='{date}']/following-sibling::div[#class='statement-download']
It's a better way you can do it by using loops if you have multiple operations
List<WebElement> statementdownload =
driver.findElements(By.xpath("//div[#class='statement-download']"));
for (int i=0;i<statementdownload.size();i++) {
statementdownload.get(i).click();
statementdownload.get(i).getText();
// You can use your condition here
}

Puppeteer (1.14.0) unable to find anchor tag by "id" although JQuery can find it

Node v10.15.3 (64-bit)
Puppeteer v1.14.0
Chromium v 75.0.3738.0 (Developer Build) (64-bit)
I am at the very last page of a site automation tool and the last button I need to press (which is actually an anchor tag with an "id" attribute) cannot be found by Puppeteer. The code is:
await page2.click('#____bs');
The error I receive is:
Error: Node is either not visible or not an HTMLElement
The HTML code is here:
<a role="button" ct="Button" rel="tooltip" title="Post"
aria-label="Please Select Post" data-toggle="cso-button" id="____bq"
class="cso-btn cso-btn cso-action cso-corner cso-btn-primary "
href="javascript:void(0)"
data-ctl-options="{'actiontype';:'ACTION','value':'Click'}"
style="display: inline-block;">Post</a>
While in debug mode with this page up, I can use JQuery to find the element easily:
$("#____bq").text()
"Post"
Therefore, why can't Puppeteer find it? Is there an alternate way I could try to click this link?
Could it also be that the control (the anchor) is outside the visible edge of the screen? I wouldn't think that would matter since I'm assuming Puppeteer is looking at the HTML and not the screen itself but doesn't hurt to ask.
Thanks in advance.
UPDATE: Here's the entire HTML that contains the anchor I'm trying to select:
<div class="row split">
<div class="clsFP-expand clsBG-expand cso-hidden cso-cont-50r cso-pad5r">
<span class="cso-pad5-ie">
<a role="button" ct="Button" rel="tooltip" title="Cancel" aria-label="Please Select Cancel" data-toggle="cso-button" id="____bo" class="cso-btn cso-btn cso-action cso-corner cso-btn-grey " href="javascript:void(0)" data-ctl-options="{"actiontype":"ACTION","value":"Click"}" >Cancel</a>
</span>
<span class="cso-pad5-ie">
<a role="button" ct="Button" rel="tooltip" title="Post" aria-label="Please Select Post" data-toggle="cso-button" id="____bs" class="cso-btn cso-btn cso-action cso-corner cso-btn-primary inactive " href="javascript:void(0)" data-ctl-options="" >Post</a>
<a role="button" ct="Button" rel="tooltip" title="Post" aria-label="Please Select Post" data-toggle="cso-button" id="____bq" class="cso-btn cso-btn cso-action cso-corner cso-btn-primary " href="javascript:void(0)" data-ctl-options="{"actiontype":"ACTION","value":"Click"}" >Post</a>
</span>
</div>
</div>
It's not that Puppeteer is not being able to get the element. That's a validation coming from Puppeteer (see https://github.com/GoogleChrome/puppeteer/blob/5ee21d97e796263857b9f3fbeaf63366179d346f/lib/JSHandle.js#L203).
According to the doc:
This method fetches an element with selector, scrolls it into view if needed, and then uses page.mouse to click in the center of the element. If there's no element matching selector, the method throws an error.
That means that Chromium should be able to scroll to that element, and that element should be visible in order to be able to click on it.

How to write xpath in selenium webdriver for below HTML expressions?

I wrote xpath for below HTML code i.e. displayed below
1. //a[#text()='Life Insurance']
2. //span[#text()='Apply now']
But I got element not found exception. If I used Absolute xpath processor then It's working and I wrote own xpath then it thrown exception.
Please tell me how to write it.
Below are the HTML code for which I need xpath.
1.<a class="mainlink" href="https://leads.hdfcbank.com/applications/webforms/apply/HDFC_Life_Click2Protect/index.aspx?promocode=P4_hp_AppNow_LI" target="" rel="nofollow width=375 height=213">Life Insurance</a>
2." <div class="menutext"> <span class="mainlink">Apply now</span> <img class="pointer" alt="Pointer" src="/assets/images/nav_pointer.png" style="display: none;"> </div> "
Try these
For 1
//a[text()='Life Insurance']
For 2
//span[text()='Apply now']
You have to remove '#' in your code.
(or)
You can also use:
//a[contains(text(),'Life Insurance')]
For 2
//span[contains(text(),'Apply now')]

Not finding the Correct xpath

I'm trying write a Python script to get some information from Google's products listed on the top right of the screen. (Usual 6 pictures with price and seller)
I am using Python, PhantomJS and Selenium
Doing a google search for "red shoe" I want my script to return the prices. I get stuck in the step where I try to even find the element containing the products. Am I missing something with my xpath?
def getTopSongs(object):
print "Working YETI"
browser = webdriver.PhantomJS('c:/projects/phantomjs/phantomjs.exe')
browser.get('http://google.com/search?q=red+shoe')
time.sleep(5)
title = browser.find_element_by_xpath('//div[contains#class, "pla-unit")]/text()[contains(., "red")]/following::b').text
From Google's webpage I element under a few nested
<div id="rhs">
...
<div class="_Pwb">
<div class="_Ohb">
<div style="width:109px" class="pla-unit">
<div class="_PD">
<div class="pla-unit-img-container">
<div class="_Z5">
<div class="_vT"><a href="http://www.somewebsite.com">
<span class="rhsl4">Nina 'Forbes' Peep Toe Pump <b>Red</b> R...</span>
<span class="rhsg3 rhsl5">Nina 'Forbes' Peep Toe Pum...</span>
<span class="rhsg4">Nina 'Forbes' Peep Toe Pu...</span></a>
</div>
<div class="_QD"><b>$78.95</b></div>
<div class="_mC">
<span class="rhsl4 a">Nordstrom</span>
<span class="rhsg3 rhsl5 a">Nordstrom</span>
<span class="rhsg4 a">Nordstrom</span>
</div>
</div>
*Update:
I added more HTML. In this example I am looking to get the text from ($78.95) annd (Norstrom)
*Update
To clarify,
<div id="rhs">
is an unique element
There are however multiple (6) elements of:
<div style="width:109px" class="pla-unit">
The elements under each category have the same name and follow the same structure and substructures
ie, there are 6
<div class="_PD">
<div class="pla-unit-img-container">
<div class="_Z5">
<div class="_vD">
<div class="_QD">
<div class="_mC">
and so on.
The main objective is to get all of the elements but for purposes of debugging I was asking help to get the first one.
The xpath for a price unit using XPathChecker on Firefox is:
id('rhs_block')/x:div[1]/x:div/x:div/x:div/x:div[1]/x:div[1]/x:div[2]/x:div[2]/x:b
You can use ancestor:: to go back up then following-sibling:: to get elements at the same level that follow it.
I haven't tried this but give it a shot:
title = browser.find_element_by_xpath('//div[contains#class, "pla-unit")]/text()[contains(., "red")]/ancestor::div/following-sibling::div[1]').text
Then to get to your div class ='mC' you just change:
following-sibling::div[1]
to
following-sibling::div[2]
and get the text from the spans under that.