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]")
Related
I have built a bot that plays an online roulette with Selenium (Selenium Grid) and Python.
When it comes to clicking on the number I want to bet on, it is extremely slow and does not manage to complete its stake (within the given time range for the bet) across all numbers that make my bet complete.
It seems like slowness may be given from the animation the button does after I click on it.
The code is very simple:
element = WebDriverWait(driver, timeout).until(EC.presence_of_element_located((By.XPATH, path)) # I manage to retrieve the WebElement, this is fast, no problem here
element.click() # this is slow
Here you can find:
how it looks now > https://drive.google.com/file/d/1dEuWTtrXHzRfXXVHhUbdNR8XtgMeWdU-/view?usp=sharing
my target > https://drive.google.com/file/d/1NUbr6rpOGjdMuClD5hby91jPVumqwLC5/view?usp=sharing (here I use the pynput library which is not my target cause I want the script to run on the server using Selenium Grid).
Anyone can help?
I'm not actually sure, is it the same problem or not. In my case, after clicking submit button on login form and redirecting to home page, my script doesn't do anything for around 4 minutes.
I've noticed, that WebElement.click() function ends execution only after page stops loading, but some trackers on site prevent page from complete loading, so I added uBlock extension and got rid of my problem.
I am using selenium webdriver, python to write a test case wherein I have to perform an action when a button appears on the screen. The tricky part over here is that if the button is not already present, I have to keep on refreshing the page till it comes and then perform the necessary actions.
I wanted to know if there's any other way around this so that I won't have to keep on refreshing the page?
Thank you for the help.
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.
So, the web app we're developing has a TV/PC mode, and i'm testing the ability to transit between these two modes. `
def pc_to_tv(self):
pc_to_tv = self.driver.find_element_by_xpath(
'html/body/div[1]/div/topbar/header/div[2]/div[2]/div[1]/button[1]')
pc_to_tv.click()
def tv_to_pc(self):
tv_to_pc = self.driver.find_element_by_xpath(
'html/body/div[1]/div/topbar/header/div[2]/div[2]/div[1]/button[2]')
tv_to_pc.click()`
The problem is, when i switch from pc to tv, the screen "zooms in", making the button appear in the same place it would be without the zoom. so, i can't click on the button with my 'tv_to_pc' method, 'cause instead on clicking on the actual button, it clicks where the button should be.
So, the solution i found was clicking on the button with coordinates, that way i'll actually click on the place i want, instead of clicking on an unclickable place like i was doing.
The thing is, i don't know how to do this, and need help on this matter.
I would suggest that you just click the button using JavaScriptExecutor. It will click it no matter where it is on the page. See How to execute a javascript in a Python webdriver and other questions for more info. The general format is
element = driver.find_element_by_id("someId")
driver.execute_script("arguments[0].click();", element)
Also... you don't want to use XPaths like that. Any XPath that starts at the HTML tag or is more than just a few levels deep is going to be very brittle. Do some googling on selenium xpaths and read some guides for more info.
try moveToElement and then perform click
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
new Actions(driver).moveToElement(element, x, y).click().perform();
x is xoffset
y is yoffset
Please see that if you use Javascript for click its not going to be native click.
We are testing a web application based on angular js. I have encountered it twice now. this time I need to click a dropdown embedded in a link tag . I can manually manipulate it with ipython, but once it run in script, the dropdown popup will not appear as what I can do it with the terminal.
Do you have any idea about this?
Judging from your comment "there is no error actually, the element is clicked", then I would suspect that the script is running fast enough to click the element before the JavaScript actions have been bound to the event. You can verify this by adding a
import time
time.sleep(4)
If the action works when there is a deliberate pause then you can be quite sure that it is a race condition between the JavaScript being bound and Selenium clicking the element.
How you deal with this is up to you. You could mark the DOM in some way when the events had been bound. That's a technique I've used in the past.
You could execute a bit of JavaScript in a loop that returned some information about the global state of the page, and use that to decide when the page was ready to interact with.