Selenium + Python: next button through click() - python

I don't understand why when I go to this page
https://www.ryanair.com/it/it/voli-low-cost/?from=BGY&out-from-date=2018-09-01&out-to-date=2018-09-30&budget=60&trip-length-from=1&trip-length-to=3
or whatever page from that website, Selenium doesn't allow me on the script to run the next page button with the code:
next_page = browser.find_element_by_xpath('/html/body/div[2]/main/div/div[2]/farefinder-widget/div/div[2]/div[2]/div/div/core-pagination/div/div[2]/a')
next_page.click()
On the HTML code:
<a ng-class="{'disabled': $ctrl.isLastPage($ctrl.currentPageIndex)}" ng-click="$ctrl.handleNextClick()" class="core-link"><span class="nav-label">Successivo</span><core-icon icon-id="glyphs.chevron-right" class="icon-22 fill-ryanair-bright-blue"><div><svg tabindex="-1" focusable="false" role="img"><use xlink:href="/it/it/voli-low-cost/?from=BGY&out-from-date=2018-09-01&out-to-date=2018-09-30&budget=60&trip-length-from=1&trip-length-to=3#glyphs.chevron-right" ng-href="/it/it/voli-low-cost/?from=BGY&out-from-date=2018-09-01&out-to-date=2018-09-30&budget=60&trip-length-from=1&trip-length-to=3#glyphs.chevron-right"></use></svg></div></core-icon></a>
Whereas If I write it on the shell, oddly enough it does work, with the same exact lines. I've also tried to give it some seconds with time.sleep, but nothing happened.

Pagination appears to be disabled for this element, i.e. <a ng-class="{'disabled': $ctrl.isLastPage..... It works for me if I click on the parent div, like so:
browser.find_element_by_css_selector(".next.vertical-center").click()
Or, if you want use your xpath, you just need to remove the last 'a':
next_step = browser.find_element_by_xpath('/html/body/div[2]/main/div/div[2]/farefinder-widget/div/div[2]/div[2]/div/div/core-pagination/div/div[2]')
For readability, I recommend the CSS selector.
EDIT: You are probably getting an exception because the element is not visible. Just need to scroll the element into view.
element = browser.find_element_by_css_selector(".next.vertical-center")
browser.execute_script("arguments[0].scrollIntoView();", element)
element.click()

Related

Element not being clicked even though it is found using Selenium

I'm trying to click on an element (radio button) using Selenium (in Python), I can't disclose the URL because it's a private corporate intranet, but will share the relevants part of code.
So basically this element is within an iframe, thus, I've used the following code to get the element:
# Select the item on main DOM that will udpate the iframe contents
wait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//*[#id='sm20']"))).click()
# Don't sleep, but only WedDriverWait...
wait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#name='ifrInterior']")))
# Select the element inside the iframe and click
wait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[#name='gestionesPropias_Equipo']"))).click()
The HTML code for the element is this:
<span class="W1">
<input type="radio" name="gestionesPropias_Equipo" value="1" onclick="javascript:indicadorPropiasEquipo(); ocultarPaginacion('1'); limpiarDatosCapaResultado();">
</span>
I'm interested in clicking this because when we click on it a drop-down is enabled:
If clicked then the dropdown is enabled:
The intersting HTML code for this is
<span id="filtroAsignado" class="W30">
<select name="nuumaAsignado" class="W84">
<option value="">[Todo mi equipo]</option></select>
</span>
Debugging a bit Selenium I can see that the elemtn is found:
And this is actually the base64 image of the element, which is the expected radio button
So I'm wondering why the element actually does not get clicked??
UPDATE: Based on request from #DebanjanB, I'm adding the HTML code from the iframe, which is enclosed inside a div in the main page:
<div id="contenido">
<iframe frameborder="0" id="ifrInterior" name="ifrInterior" src="Seguimiento.do?metodo=inicio" scrolling="auto" frameborder="0"></iframe>
</div>
Actually if I look for the word "iframe", there's only one...
Now checking the iframe source itself, has several iframes hidden but the element I need to interact with is in the iframe mentioned above, the only thing that I forgot to mention is that it's inside a form, but I guess that's not relevant? You can see the whole structure in the following image:
Great question. If you know that selenium found the element, you can use Javascript to click the element directly.
The syntax is:
driver.execute_script("arguments[0].click();", element)
You can also do this, which works the same way:
automate.execute_script("arguments[0].click();", wait.until(EC.element_to_be_clickable((By.XPATH, 'Your xpath here'))))
Essentially you are having Selenium run a javascript click on the element you have found which bypasses Selenium. Let me know if this helps!
I don't see any such issue with your code block either. Perhaps you can try out either of the following options:
Using ActionChains:
ActionChains(driver).move_to_element(WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[#name='gestionesPropias_Equipo' and #type='radio']")))).click().perform()
Using executeScript() method:
driver.execute_script("arguments[0].click();", WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[#name='gestionesPropias_Equipo' and #type='radio']"))))

Element is not clickable (the button is blocking by other element)

I'm trying to click on this button: browser.find_element_by_id('btnSearch')
But this button is blocking by this div tag: <div id="actionSearch" class="row pull-right">
How do I go around to click this button with id='btnSearch" while it's blocking by the actionSearch div?
I tried the following:
browser.find_element_by_id('btnSearch').click()
browser.implicitly_wait(10)
el = browser.find_element_by_xpath('//*[#id="btnSearch"]')
ActionChains(browser).move_to_element_with_offset(el, 1827, 270)
ActionChains(browser).click()
ActionChains(browser).perform()
element = browser.find_element_by_id('btnSearch')
browser.execute_script("arguments[0].click();", element)
wait(browser, 10).until(EC.element_to_be_clickable((By.XPATH, //*[#id="btnSearch"]'))).click()
none of these work.
Can anyone help me with this? I've spent two days trying to click this button!! Please help!
Considering provided image of HTML source (tip: do not provide it as image, but as text instead) I can assume that required element located in the bottom of page and you might need to scroll page down to be able to handle it.
Try below code
link = browser.find_element_by_id("btnSearch")
browser.execute_script("arguments[0].scrollIntoView()", link)
link.click()
Note that link is not a pseudo-element (is not located inside ::before/::after pseudo-element), so it can not be the cause of your problem
As for your code:
ActionChains(browser).move_to_element_with_offset(el, 1827, 270)
ActionChains(browser).click()
ActionChains(browser).perform()
Here you're trying to make scroll to link with huge offset and then you make click on current mouse position - not on link
You can try to modify it as
ActionChains(browser).move_to_element(el)
ActionChains(browser).click(el) # Pass WebElement you want to click as argument to `click()`
ActionChains(browser).perform()

Not able to click a button in Selenium (Booking.com)

I am programming a python scraper with help of Selenium. The first few steps are:
goes on booking.com, insert a city name, selects the first date and then tries to open the check-out calendar.
Here is where my problem occurs. I am not able to click the check-out calendar button (The important are of the website).
I tried to click every element regarding to the to check-out calendar (The elements of check-out calendar) with element.click(). I also tried the method
element = self.browser.find_element_by_xpath('(//div[contains(#class,"checkout-field")]//button[#aria-label="Open calendar"])[1]') self.browser.execute_script("arguments[0].click();", element)
It either does nothing (in case of execute.script() and click() on div elements) or it throws following exception when directly clicking the button:
Element <button class="sb-date-field__icon sb-date-field__icon-btn bk-svg-wrapper"
type="button"> is not clickable at point (367.5,316.29998779296875)
because another element <div class="sb-date-field__display"> obscures it
Here is a short code to test it:
browser = webdriver.Firefox()
browser.get("https://www.booking.com/")
wait = WebDriverWait(browser, 5)
element = wait.until(EC.presence_of_element_located((
By.XPATH, '(//div[contains(#class,"checkout-field")]//button[#aria-label="Open calendar"])[1]')))
element = wait.until(EC.element_to_be_clickable((
By.XPATH, '(//div[contains(#class,"checkout-field")]//button[#aria-label="Open calendar"])[1]')))
element.click()
I have a temporarily solution for my problem but I am not satisfied with it.
element = browser.find_element_by_xpath('(//div[contains(#class,"checkout-field")]//button[#aria-label="Open calendar"])[1]')
hov = ActionChains(browser).move_to_element(element)
hov.click().perform()
This will open the calendar by hovering over the object and clicking it. This strangely opens the calendar.
The methods mentioned above still don't work.
Define clicka as an xpath. Now use executescript to click the element.
driver.execute_script("arguments[0].click();", clicka)
I'm not 100% sure that I got everything you posted, because the layout is a bit messy.
However, I tried to test the issue with both Selenium Java and Firefox Scratchpad (a Web Developer tool that allows to run JavaScript scripts) and it worked perfectly - the button was clickable on both of them.
If you're interested in further testing using this tool, this is the code I've used:
In JavaScript:
function getElementByXpath(path) {
return document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}
var myElement = getElementByXpath('(//div[contains(#class,"checkout-field")]//button[#aria-label="Open calendar"])[1]')
myElement.click()
and in Java:
FirefoxDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver, 10);
driver.navigate().to("https://www.booking.com");
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("(//div[contains(#class,'checkout-field')]//button[#aria-label='Open calendar'])[1]")));
driver.findElement(By.xpath("(//div[contains(#class,'checkout-field')]//button[#aria-label='Open calendar'])[1]")).click();
System.out.println("success");
if your are having the control check out button on all the web site managing with explicit wait required lots of codding you can use implicit wait below is in the java.
System.setProperty("webdriver.chrome.driver",
"G:\\TopsAssignment\\SampleJavaExample\\lib\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);

Python selenium - get element by its xPath and access it

I am using Python and Selenium to scrape a webpage, in some cases, I can't get it to work,
*
I would like to access the element with text 'PInt', wich is the second link in the below code.
The xPath for it (copied from Developer console) is: //[#id="submenu1"]/a[2]
<div id="divTest" onscroll="SetDivPosition();" style="height: 861px;">
<div class="menuTitle" id="title1">
</div>
<div class="subtitle" id="submenu1">
<img src="images/spacer.gif" border="0" width="2px" height="12px">
Mov<br>
<img src="images/spacer.gif" border="0" width="2px" height="12px">
PInt<br>
<img src="images/spacer.gif" border="0" width="2px" height="12px">
SWAM / SWIF<br>
</div>
...
A snipped of my code is:
try:
res = driver.find_elements_by_link_text('PInt')
print("res1:{}".format(res))
res = driver.find_element(By.XPATH,'//*[#id="submenu1"]/a[3]')
print("res:{} type[0]:{}".format(res,res[0]))
itm1 = res[0]
itm1.click()
I get the error:
Unable to locate element:
{"method":"xpath","selector":"//*[#id="submenu1"]/a[2]"}
My question is, how can I get the right xPath of the element or any other way to access the element?
UPDATE:
This might be important, the issue with
Message: invalid selector: Unable to locate an element with the xpath expression (and I've tried all proposed solutions) might be that this is after authenticate in the webpage (User + Pwd) before, everything works.
I noticed that the url driver.current_url after login is static (asp page).
Also this part I am trying to access in a frameset and frame
html > frameset > frameset > frame:nth-child(1)
Thanks to #JeffC to point me in the right direction.
since the page has some frames, I manage to access the element first by switching to the right frame (using xPath)
and then access the element.
driver.switch_to.default_content()
driver.switch_to.frame(driver.find_element_by_xpath('html / frameset / frameset / frame[1]'))
driver.find_element_by_xpath("//a[contains(text(),'PInt')]").click()
BTW, in case you want to run the script from a crontab,you need to setup a display:
30 5 * * * export DISPLAY=:0; python /usr/.../main.py
To see a full list of all the ways of selecting elements using selenium, you can read all about it in the documentation.
Using xpath:
res = driver.find_element_by_xpath(u'//*[#id="submenu1"]/a[2]')
Using css selector:
res = driver.find_element_by_css_selector('#submenu1 a:nth-of-type(2)')
Try with any of the below xpath. Sometimes automatically generated xpath does not work.
//a[contains(text(),'PInt')]
or
//div[#id='submenu1']//a[contains(text(),'PInt')]
Also I would suggest you to set some wait time before clicking on above link in case if above xpath does not work
To find xPath in chrome:
Right click the element you want
Inspect, which will open the developer window and highlight the selected element.
Right click the highlighted element and choose copy > copy by xpath
Here is a list of all the different ways to locate an element Locating Elements

Python+Selenium, can't click the 'button' wrapped by span

I am new to selenium here. I am trying to use selenium to click a 'more' button to expand the review section everytime after refreshing the page.
The website is TripAdvisor. The logic of more button is, as long as you click on the first more button, it will automatically expand all the review sections for you. In other words, you just need to click on the first 'more' button.
All buttons have a similar class name. An example is like taLnk.hvrIE6.tr415411081.moreLink.ulBlueLinks. Only the numbers part changes everytime.
The full element look like this:
<span class="taLnk hvrIE6 tr413756996 moreLink ulBlueLinks" onclick=" var options = {
flow: 'CORE_COMBINED',
pid: 39415,
onSuccess: function() { ta.util.cookie.setPIDCookie(2247); ta.call('ta.servlet.Reviews.expandReviews', {type: 'dummy'}, ta.id('review_413756996'), 'review_413756996', '1', 2247);; window.location.hash = 'review_413756996'; }
};
ta.call('ta.registration.RegOverlay.show', {type: 'dummy'}, ta.id('review_413756996'), options);
return false;
">
More </span>
I have tried several ways to get the button click. But since it is an onclick event wrapped by span, I can't successfully get it clicked.
My last version looks like this:
driver = webdriver.Firefox()
driver.get(newurl)
page_source = driver.page_source
soup = BeautifulSoup(page_source)
moreID = soup.find("span", class_=re.compile(r'.*\bmoreLink\b.*'))['class']
moreID = '.'.join(moreID[0:(len(moreID)+1)])
moreButton = 'span.' + moreID
button = driver.find_element_by_css_selector(moreButton)
button.click()
time.sleep(10)
However, I keep getting the error message like this:
WebDriverException: Message: Element is not clickable at point (318.5,
7.100006103515625). Other element would receive the click....
Can you advise me on how to fix the problem? Any help will be appreciated!
WebDriverException: Message: Element is not clickable at point (318.5, 7.100006103515625). Other element would receive the click....
This error to be occur when element is not in the view port and selenium couldn't click due to some other overlay element on it. In this case you should try one of these following solution :-
You can try using ActionChains to reach that element before click as below :-
from selenium.webdriver.common.action_chains import ActionChains
button = driver.find_element_by_css_selector(moreButton)
ActionChains(button).move_to_element(element).click().perform()
You can try using execute_script() to reach that element before click as :-
driver.execute_script("arguments[0].scrollIntoView(true)", button)
button.click()
You can try using JavaScript::click() with execute_script() but this JavaScript::click() defeats the purpose of the test. First because it doesn't generate all the events like a real click (focus, blur, mousedown, mouseup...) and second because it doesn't guarantee that a real user can interact with the element. But to get rid from this issues you can consider it as an alternate solution.
driver.execute_script("arguments[0].click()", button)
Note:- Before using these options make sure you're trying to interact with correct element using with correct locator, otherwise WebElement.click() would work well after wait until element visible and clickable using WebDriverWait.
Try using an ActionChains:
from selenium.webdriver.common.action_chains import ActionChains
# Your existing code here
# Minus the `button.click()` line
ActionChains(driver).move_to_element(button).cli‌​ck().perform()
I have used this technique when I need to click on a <div> or a <span> element, rather than an actual button or link.

Categories

Resources