Selenium can't locate elements inside HTML doc within another HTML doc - python

I don't know what's exactly the thing that Amazon opens when you click the "buy now" button, I tryed to search on internet but couldn't find a clear answer. It could be a pop-up or an iframe, but they call it "popover" in their source code, which I have no clue what it is.
The point is, once you open this "popover", Selenium is unable to parse any part of that frame since it's a standalone separate HTML doc. I'm not sure if it's an iframe as I've never seen an iframe like that, so any guide I serached online about how to switch context using an Handler to an iframe doesn't work here. I couldn't find an ID, name, or anything significant to allow Selenium to parse the frame.
image showing the "popover"
If anyone has any clue how this HTML element is actually called and how to allow Selenium to parse it, please let me know, thanks.

I checked HTML of the page and here are my findings:
'Close' button is not in iFrame
Popup content itself is in iframe
See screenshot below:
What does it mean for you:
In order to click on the button 'Close' (e.g. by css selector button[class*='a-button-close']) you do not need to switch to any frames. If you are failing to click on the button - I would assume that you are missing selenium wait. There is a small delay after you clicking on "Buy Now" button and before popup actually loads - you need to explicitly wait for it to load. See https://selenium-python.readthedocs.io/waits.html for more details on selenium waits. I would recommend using visibility_of_element_located or visibility_of to wait for popup/button to appear (load) in your case.
If you did any operations in the popup itself (e.g. if you clicked on some links inside of it) - you most likely switched to the context of the iFrame with driver.switch_to.frame(iframe). In this case - you need to switch back to main context with driver.switch_to.default_content() in order to click on the 'Close' button (since it is outside of iframe).
I highly recommend learning runtime evaluate technique - it will save you hours on debugging your applications - see https://www.jetbrains.com/pycharm/guide/tips/evaluate-expression/
P.S. next time when asking question - please post your code (at least on high level) - it will help with localizing issue.

Related

Check AngularJS checkbox with Selenium

HTML Source here
It seems trivial, but after hours of attempts I cannot manage to check this checkbox using Selenium. I am able to select the element no problem, and have even been able to 'highlight' (see code snippet below) it by sending Keys.RETURN to the element, but on attempting to click it, nothing happens. Perhaps someone has an idea?
What I have tried already:
Using with WebDriverWait
Using multiple and different combinations of .click()/.send_keys(Keys.RETURN)
Just about every combination of XPATH/css selector/id/name/classname/text that Selenium would accept for the element, and all of its children and most of its parents (including spans/labels, and the text inside the label itself).
Directly clicking the element/label coordinates using actions (nothing happens, even when I can 100% confirm it is clicking the right spot by using context_click()).
Using execute_script to change the "checked" attribute to True (the checkbox appears checked, but it is clear it is only client side as a box that is supposed to render when it is actually clicked doesn't).
Using execute_script to change the class to 'ng-valid ng-not-empty ng-dirty ng-valid-parse ng-touched'
Here is the code that I feel got me the closest (it is 'highlighting' the box as seen here)
browser.find_element(By.ID, "sp_formfield_none_of_the_above").send_keys(Keys.RETURN)
Managed to solve it after another while of testing. Hopefully this helps someone in the future. I had to use JS to execute .click() on the checkbox element. In retrospect, I should have tried this solution sooner. See code snippet:
cb_none = browser.find_element(By.ID, 'sp_formfield_none_of_the_above')
browser.execute_script("arguments[0].click();", cb_none)

How can I click "invisible" reCAPTCHA buttons using Selenium web automation?

I am using Python and Selenium to automate this website: https://prenotami.esteri.it
The script I made fills out a form and then clicks a button to advance to the next page. These actions are carried out using Selenium's find_element_by_xpath() function. Recently, the website added a reCAPTCHA that pops up after the button is clicked, and must be completed before advancing.
I have already written a Python script that is capable of surpassing this type of captchas by using the audio option. However, in this particular website, I am not able to find the xpath to the audio button of the reCAPTCHA. Although there is an iframe that contains the reCAPTCHA, there seems not to be anything inside it.
In the first attached image you can see how this website's reCAPTCHA looks like in HTML, compared to other website that is visible in the second image, where a #document can be seen inside the iframe.
My intention is to run this program using headless Chrome, so I can't relay in any mouse control functions offered by pyautogui for example.
I've been scratching my head around this problem for a while, so any advice is useful. Thanks!
Edit: after some research I have found that this type of reCAPTCHA that doesn't need to check a "I am not a robot" checkbox is called "invisible reCAPTCHA". The captcha only pops up if the detected activity is suspicious (for example clicking too fast). I have tried adding random waits and movements to mimic human behaviour, but the captcha still appears after some tries. Since I don't think there is a way to avoid the captcha from appearing 100% of the times, the question of how to click the buttons using Selenium's find_element_by_xpath() function remains the same. Leaving this as a note just in case someone finds it useful.
Ever tried to use the following function:
add_argument("-auto-open-devtools-for-tabs")
I managed to interact with captcha
If the position is always fixed, you can use PyAutoGUI to move the mouse and click on it
import pyautogui
pyautogui.click(100, 100) # button coordinates
Since, it is in iframe, we need to move our selenium pointing to iframe and then use your xpath.
driver.switch_to.frame("c-la7g7xqfbit4")
capchaBtn = driver.find_element_by_xpath("(//button[#id='recaptcha-audio-button'])[2]")

With selenium on python don't know how to shut down a banner which is preventing selenium from accessing the page content

I'm trying to open a site with Selenium (with Python) using Chrome browser, but when I do, a full screen promo banner immediately pops-up and I can't access the site content unless I close it.
On the top right there is an "x" as if it was a quit button, but actually it's an element ::before
and from its description it seems to me that it doesn't contain any button element.
If I operate manually, both clicking on the x and on the upper part of the page outside the banner, the latter closes, but I really don't understand how to access it with selenium.
The webpage I'm trying to open is https://sports.bwin.it/it/sports
Needless to say I'm quite inexperienced, so I hope this question won't sound too basic, but I wasn't able to find a solutione in the selenium docs or on the web; if someone could give me any hint I would appreciate it.
This is a screenshot from the page I'm talking about
This is part of the html code from the web page; the element I am talking about is the one pointed by the arrow;
Based on your screen shot the xpath you want to use would be something like this:
//*[#data-id='dj_sports_c_ovl_br']//span
full code would be something like this:
element = WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.XPATH, "//*[#data-id='dj_sports_c_ovl_br']//span"))
)
element.click();

Unable to locate/click pop-up button with Selenium in Python

I'm using Selenium in Python 3 to access webpages, and I want to click on a pop-up button, but I am unable to locate it with Selenium.
What I'm describing below applies to a number of sites with a pop-up, so I'll use a simple example.
url = "https://www.google.co.uk"
from selenium import webdriver
driver = webdriver.Firefox()
driver.implicitly_wait(10)
driver.get(url)
The page has a pop-up for agreeing to cookies.
I want the script to click on the "I agree" button, but I'm unable to locate it.
I've found a few questions and posts about this online (including on Stackoverflow), but all the suggestions I found seem to fall in one of the following categories and don't seem to work for me.
Wait longer for the pop-up to actually load.
I've tried adding delays, and in fact, I'm testing this interactively, so I can wait all I want for the page to load before I try to locate the button, but it doesn't make any difference.
Use something like driver.switch_to.alert
I get a NoAlertPresentException. The pop-up doesn't seem to be an alert.
Locate the element using driver.find_element.
This doesn't work either, regardless of which approach I use (xpath, class name, text etc.). I can find elements from the page under the pop-up, but nothing from the pop-up itself. For example,
# Elements in main page (under pop-up)
driver.find_element_by_partial_link_text("Sign in") # returns FirefoxWebElement
driver.find_element_by_class_name("gb_g") # returns FirefoxWebElement
# Elements on the pop-up
driver.find_element_by_partial_link_text("I agree") # NoSuchElementException
driver.find_element_by_class_name("RveJvd snByac") # NoSuchElementException
The popup just doesn't seem to be there in the page source. In fact, if I try looking at the loaded page source from the browser, I can't find anything related to the pop-up. I understand that many sites use client-side scripts to load elements dynamically, so many elements wouldn't show up in the raw source, but that was the point of using Selenium: to load the page, interpret the scripts and access the end result.
So, what am I doing wrong? Where is the pop-up coming from, and how can I access it?

How to automate chrome extension that interacts with the parent webpage?

I want to automate the testing for a chrome-extension.
I have used selenium-python to automate the parent web-page , but i am unable to use selenium to automate the chrome-extension because selenium is bound to the web-page view,so i am not able to click the chrome extension icon present in the title bar of the google chrome. Due to this limitation, i tried using sikuli to click on the chrome-extension icon ,but i couldn't get the DOM of the chrome-extension popup HTML that appear when the extension's icon is clicked, as i had to access the text displayed by the extension's pop up html page and then evaluated it.My test failed.
I thought i could use shift_to_window() but in vain,because its a pop up html, and hence i cant shift.If instead i use sikuli ,as the test cases increased , the amount of pictures needed to automate it will also increase, so it won't be feasible.
Sample Screenshot,
In this picture,the web-store page is the parent page and the small popup in the right top corner,is the pop-up i am talking about, that appear after clicking the chrome extension . So basically i have to interact with that popup HTML.
I didn't quite understand why you can't automate whatever webpage you have with Selenium and what is the limitation you are describing. Perhaps an example such as screenshot or even a link to the relevant webpage can help. Furthermore, I don't understand why do being unable to extract DOM from a page is a limitation while using Sikuli. Sikuli has nothing to gain from the DOM, it purely based on visual content of the screen.
I would attempt to handle the popup you are describing using using standard Selenium functionality so something like this:
driver.switchTo().alert().dismiss();
There are additional alert handling options so you can choose what suits you most.

Categories