Unable to select reCaptchaV2 checkbox in SeleniumBase - python

I have a SeleniumBase code like this
from seleniumbase import SB
from func_timeout import func_set_timeout, FunctionTimedOut
def checkbox():
print('- click checkbox')
checkbox = 'span#recaptcha-anchor'
try:
sb.wait_for_element(checkbox)
sb.click(checkbox)
sb.sleep(4)
except FunctionTimedOut as e:
print('- 👀 checkbox:', e)
When I call checkbox() it gives error and the browser crashes quickly without clicking the checkbox
I tried replacing
checkbox = 'id#recaptcha-anchor-label'
checkbox = 'id#rc-anchor-center-item'
but it didn't work

You might want to try avoiding the captcha altogether by running SeleniumBase in undetected-chromedriver mode (set uc=True, or run with --uc):
from seleniumbase import SB
with SB(uc=True) as sb:
sb.open("https://nowsecure.nl/#relax")
try:
sb.assert_text("OH YEAH, you passed!", "h1", timeout=7)
sb.post_message("Selenium wasn't detected!", duration=2)
print("\n Success! Website did not detect Selenium! ")
except Exception:
print("\n Sorry! Selenium was detected!")
If you still need to go through the captcha, then make sure that if you need to click something in an iframe, that you switch to the iframe first, such as with sb.switch_to_frame("iframe").
Also, the sb.click(selector) method will automatically wait for the element, which means that calling sb.wait_for_element(selector) before that is unnecessary.

Related

SendMouseWheelEvent does not work on subsequent page loads

I'm trying to use SendMouseWheelEvent to pass mouse scrolls into the browser, but it is only working on the first page load. Any subsequent pageloads after that, it does not work, unless the browser is interferred with actual mouse scroll.
I've prepared the following script. The "errorrep" is actually the name of the script itself, as "errorrep.py", into which I'm assigning the browser as "mybrowser".
How can I have the browser correctly work with SendMouseWheelEvent on subsequent pageloads?
cefpython version is 66.1.
"""
SendMouseWheelEvent is correctly performed on the first page load. On any pageloads after that, it does not seem to work, but it works again when the actual mouse device performs a scroll on the webpage
'# test 1' which does a javascript code 'scrollBy', works on every pageload.
'# test 2' which does a SendMouseWheelEvent, only works on first page load.
"""
from cefpython3 import cefpython as cef
import time
from threading import Thread
import errorrep
mybrowser = None
def main():
cef.Initialize()
browser = cef.CreateBrowserSync(url="https://stackoverflow.com/")
browser.SetClientHandler(LoadHandler())
errorrep.mybrowser = browser
cef.MessageLoop()
del browser
cef.Shutdown()
class LoadHandler(object):
def OnLoadingStateChange(self, browser, is_loading, **_):
if not is_loading:
Thread(target=test).start()
def test():
print("Page loading is complete!")
for i in range(5):
print('scrolling')
# test 1
errorrep.mybrowser.ExecuteJavascript(jsCode="""scrollBy(0,25)""")
# test 2
# errorrep.mybrowser.SendMouseWheelEvent(0,0,0,-120, cef.EVENTFLAG_NONE)
time.sleep(1)
print('opening new page, clicking on the logo link')
errorrep.mybrowser.ExecuteJavascript(jsCode="""document.getElementsByClassName('s-topbar--logo js-gps-track')[0].click();""")
if __name__ == '__main__':
main()

Restart python program whenever it encounters an exception

So I've got a selenium python script that occasionally runs into the following error at differing sections in my code:
Exception has occurred: WebDriverException
Message: unknown error: cannot determine loading status
from target frame detached
But when I encounter this error, if I re-run the program without changing anything, everything works again (so I know that it's either a problem with the website or the webdriver). In the meantime, I was wondering if there was a way to tell python to restart the program if a WebDriverException is encountered. Any help would be greatly appreciated, thank you.
You could try os.execv(), according to here, it enables a python script to be restarted, but you need to clean the buffers etc using this C-like function sys.stdout.flush()
try:
<your block of code>
except WebDriverException:
print(<Your Error>)
import os
import sys
sys.stdout.flush()
os.execv(sys.argv[0], sys.argv)
You could simply use the os module to do this: os.execv(sys.argv[0], sys.argv)
Use a main() function as a starting point for your program, and trigger that function again whenever you need to restart. Something like
def foo1():
return
def foo2():
try:
...
except:
main()
def main():
foo1()
foo2()
if __name__ == "main":
main()
If the error occurs because it does not find a certain tag, you could put a wait
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
or worst case
browser.implicitly_wait(5)
or
time.sleep(5)
which waits 5 seconds for the element to appear

Click event for a notification in python with Plyer

while(True):
plyer.notification.notify(
title = title,
message = message,
app_icon = icon,
timeout = 50
)
time.sleep(3600)
I want to be able to access a link when the notification is clicked. I have not found anything like a click event in the source code. I was thinking that maybe it could be called when the timeout is 0 or something similar. If there is another way of doing it without plyer it could also work for me, but I have not found anything. Thanks in advance.
Try win10toast-click. It is not in-built so you have to pip install it.
You can use
from win10toast_click import ToastNotifier
to import it
You can use it by typing
toaster = ToastNotifier() toaster.show_toast(title=,message=,icon_path=,duration=,threaded=True,callback_on_click=yourfunction )
after that you could use webbrowser module to create your function to open the link

Selenium Alert Handling Python

So I am using Selenium to simply go to a given list of websites and take a screenshot of them. However I have run into some having alerts and some do not. I am looking to do something along the lines of if alert then this else keep moving.
Here is my current code
from selenium import webdriver
import pandas as pd
import time
path = "C:/Users/dge/Desktop/Database/NewPythonProject/html Grabber/Output/Pics/"
df = pd.DataFrame()
df = df.append(pd.read_csv('crime.csv'), ignore_index=True)
driver = webdriver.Chrome('C:/Users/dge/Desktop/Database/NewPythonProject/html Grabber/chromedriver.exe')
for i in df.index:
print(i)
pic = path + df['site'][i] + '.png'
driver.get('http://' + df['site'][i])
time.sleep(5)
driver.save_screenshot(pic)
I've seen this but just not sure how to add it in the loop
driver.find_element_by_id('').click()
alert = driver.switch_to_alert()
The best way to put this may be to say ignore any errors and continue on through my list of urls.
JavaScript can create alert(), confirm() or prompt()
To press button OK
driver.switch_to.alert.accept() # press OK
To press button CANCEL (which exists only in confirm() and prompt())
driver.switch_to.alert.dismiss() # press CANCEL
To put some text in prompt() before accepting it
prompt = driver.switch_to.alert
prompt.send_keys('foo bar')
prompt.accept()
There is no function to check if alert is displayed
but you can put it in try/except to catch error when there is no alert.
try:
driver.switch_to.alert.accept() # press OK
#driver.switch_to.alert.dismiss() # press CANCEL
except Exception as ex:
print('Exception:', ex)
Minimal working example.
Because I don't know page which displays alert so I use execute_script to display it.
from selenium import webdriver
import time
#driver = webdriver.Firefox()
driver = webdriver.Chrome()
driver.get('http://google.com')
# --- test when there is alert ---
driver.execute_script("console.log('alert: ' + alert('Hello World!'))")
#driver.execute_script("console.log('alert: ' + confirm('Hello World!'))")
#driver.execute_script("console.log('alert: ' + prompt('Hello World!'))")
time.sleep(2)
try:
driver.switch_to.alert.accept() # press OK
#driver.switch_to.alert.dismiss() # press CANCEL
except Exception as ex:
print('Exception:', ex)
# --- test when there is no alert ---
try:
driver.switch_to.alert.accept() # press OK
#driver.switch_to.alert.dismiss() # press CANCEL
except Exception as ex:
print('Exception:', ex)
# ---
driver.save_screenshot('image.png')
driver.close()
BTW: if you want to first try to press CANCEL and when it doesn't work then press OK
try:
driver.switch_to.alert.dismiss() # press CANCEL
except Exception as ex:
print('Exception:', ex)
try:
driver.switch_to.alert.accept() # press OK
except Exception as ex:
print('Exception:', ex)
BTW: different problem can be popup notifications or geolocation alerts
How to click Allow on Show Notifications popup using Selenium Webdriver

Python selenium script to continue running if element is not found

I am dealing with a pop up issue that seems to be random before I click on a button. I want to know if there is any way I can check if the element is displayed and click it, if it is not displayed, i want it to continue running the script. my current script keeps getting an error. when the pop up is displayed, my script runs PERFECT. my error takes place on my script at the
onetouch = self.driver.find_element _by_xpath("").
Here is a picture of my error:
self.driver.get(redirecturl)
self.driver.implicitly_wait(180)
login_frame = self.driver.find_element_by_name('injectedUl')
# switch to frame to access inputs
self.driver.switch_to.frame(login_frame)
# we now have access to the inputs
email = self.driver.find_element_by_id('email')
password = self.driver.find_element_by_id('password')
button = self.driver.find_element_by_id('btnLogin')
# input your email and password below
email.send_keys('')
password.send_keys('')
button.click()
#############
onetouch = self.driver.find_element_by_xpath(".//*[#id='memberReview']/div[2]/div/div/div[2]/div[1]/div[1]/a")
if onetouch.is_displayed():
time.sleep(2)
onetouch.click()
else:
print "onetouch not present....continuing script"
button2 = self.driver.find_element_by_id('confirmButtonTop')
button2.click()
button3 = self.driver.find_element_by_name('dwfrm_payment_paypal')
# if you want to test the program without placing an order, delete the button3.click() below this.........
button3.click
Actually find_element_by_xpath always returns either element or throws exception, So if there is no element by provided locator you can't execute is_displayed(). You should try using find_elements_by_xpath instead and check the length as below :-
onetouch = self.driver.find_elements_by_xpath(".//*[#id='memberReview']/div[2]/div/div/div[2]/div[1]/div[1]/a")
if len(onetouch) > 0:
time.sleep(2)
onetouch[0].click()
else:
print "onetouch not present....continuing script"
-------
Try following:
from selenium.common.exceptions import NoSuchElementException
try:
time.sleep(2)
self.driver.find_element_by_xpath(".//*[#id='memberReview']/div[2]/div/div/div[2]/div[1]/div[1]/a").click()
except NoSuchElementException:
print "onetouch not present....continuing script"

Categories