Selenium: How to deal with the situation where being treated as robots - python

I am using Selenium to simulate login with Chrome browser. The login page has Slider button which needs to be dragged to complete the login process.
The weird thing is that if I open the web page using driver.get(page). Then sliding verification code will always fail even I manually enter the username, pwd and drag the slider.
I tried to add user-agent but no help.
Is there any other way? I understand that we can add user-data to skip this part but I just want to figure it out first.
The slider verification code will display if you try to log in more than once. It seems that the web page just detect you are using the script to log in.
The error will be like:" ops, failed to verify. Please refresh again". Then I use driver.find_element_by_xpath("//*[#id='nocaptcha']/div/span/a").click() to refresh the slider.
Thanks in advance.
driver = webdriver.Chrome()
driver.get("https://login.taobao.com/member/login.jhtml?spm=a21bo.2017.754894437.1.5af911d95pqPfs&f=top&redirectURL=https%3A%2F%2Fwww.taobao.com%2F")
action = ActionChains(driver)
login()
def login():
driver.find_element_by_class_name("login-switch").click()
driver.find_element_by_id('TPL_username_1').clear()
driver.find_element_by_id('TPL_username_1').send_keys('xxx')
driver.find_element_by_id('TPL_password_1').clear()
driver.find_element_by_id('TPL_password_1').send_keys("xxx")
time.sleep(1.5)
# driver.find_element_by_id('J_SubmitStatic').click()
Slider()
def Slider():
#Sliding verification code
while True:
try:
slip=driver.find_element_by_xpath("//*[#id='nc_1_n1z']")
action.click_and_hold(slip).perform()
action.move_by_offset(150,0)
time.sleep(0.8)
action.move_by_offset(148,0)
action.release().perform()
time.sleep(2)
text = driver.find_element_by_xpath("//*[#id='nc_1__scale_text']/span")
if text.text.startswith("请在下方"):
print("Successful")
break
if text.text.startswith("请点击"):
print("Successful")
break
if text.text.startswith("请按住"):
print("Failed. Try again")
continue
except Exception:
##Error occurs, click the "Refresh" button to refresh the sliding verification code again
driver.find_element_by_xpath("//*[#id='nocaptcha']/div/span/a").click()
driver.find_element_by_id('J_SubmitStatic').click()

Related

Selenium : switch to modal window handle gives error

I have this webpage https://account.proton.me/login?language=en where I am trying to switch to modal after logging in to the page. Please note that the modal appears even if you give wrong id and password, so to reproduce you can use the same code below
driver.get('https://account.proton.me/login?language=en')
usernameField = driver.find_element(By.XPATH,'//*[#id="username"]')
usernameField.send_keys("kuchbhirandom#some.thing")
passwordField = driver.find_element(By.XPATH,'//*[#id="password"]')
passwordField.send_keys("yehbhikuchbhi")
loginbutton = driver.find_element(By.XPATH,'//button[#type="submit"]')
loginbutton.click()
The above code gives us the modal
I ttried checking the window handles and switching to them one by one which gives me
driver.window_handles
['CDwindow-34B695696D2295F87F84F06321D10117', 'CDwindow-212C47AEC0CCD8240A4F9675D5B5BEF2', 'CDwindow-5A39DFE9B9C75CFA7316BF2098765D05', 'CDwindow-796B9EF6777039A036CCF7C3D452807A', 'CDwindow-1DF355426CF56902DC339955FF55C9AE', 'CDwindow-1B700B499C716086FA269E89B0ED3835']
for handle in driver.window_handles:
driver.switch_to.window(handle)
try:
checkbox = driver.find_element(By.XPATH,'//div[#id="checkbox"]')
print('found')
except:
pass
but I get the same error "No such element"
Talking about solving the captch : I have an external API that does it for me, but I need to click that check box here, but stuck in switching to the modal part
Note that : to reproduce issue you can use same code above, no need to create account.
Problem is that you have 2 nested iframes in the site,
You'll have to perform driver.switch_to.frame() for each of them:
# After pressing "sign-in"
captcha_iframe = driver.find_element(By.CSS_SELECTOR, '[title="Captcha"]')
driver.switch_to.frame(captcha_iframe)
inner_iframe = driver.find_element(By.CSS_SELECTOR, 'iframe')
driver.switch_to.frame(inner_iframe)
# Perform captcha check
driver.find_element(By.CSS_SELECTOR, '#checkbox').click()
Notice that after each switch_to, I directly use the new driver's context, and I do not perform a search under the element I found.

Selenium gives Server Error 500 after click (Django, pytest)

I have a Django app that I want to test via pytest and Selenium.
The routine I'm trying to go through is to let Selenium log in, then go to the menu, choose one of the options. This redirects to a new page, which is found fine. There, I let selenium enter data and click a button to start a submission. This, too, works, and redirects to a third page.
On this third "your submission was created successfully" page, there is a link displayed that the user can click to collect the results of their submission (this page . This link is displayed correctly, the href URL is fine. But when I let Selenium click on it, I suddenly get a Server Error 500:
<html lang="en"><head>
<title>Server Error (500)</title>
</head>
<body>
<h1>Server Error (500)</h1><p></p>
</body></html>
When I do the exact same thing manually, it works fine.
Here's my test code (slightly simplified):
#pytest.fixture(scope="class")
def chrome_driver_init(request):
options = webdriver.ChromeOptions()
options.headless = True
options.binary_location = CHROME_BIN_PATH
driver = webdriver.Chrome(service=CHROME_SERVICE, options=options)
request.cls.driver = driver
yield
driver.quit()
#pytest.mark.django_db
#pytest.mark.usefixtures("chrome_driver_init")
class SubmissionTest(LiveServerTestCase):
def test_adding_submission(self):
self.driver.get(self.live_server_url)
username = TEST_USER
pwd = TEST_USER_PWD
User = get_user_model()
user = User.objects.create_user(username=username, password=pwd)
user.save()
# click 'Login':
self.driver.find_element(By.LINK_TEXT, "Login").click()
# now on Login page, log in via Selenium:
username_field = self.driver.find_element(By.NAME, "username")
pwd_field = self.driver.find_element(By.NAME, "password")
submit_btn = self.driver.find_element(By.ID, "form_field")
username_field.send_keys(TEST_USER)
pwd_field.send_keys(TEST_USER_PWD)
submit_btn.click()
# now logged in, go to desired menu point:
self.driver.find_element(By.LINK_TEXT, "MenuPoint 1").click()
assert self.driver.title == "MenuPoint 1" # redirection works fine
## find various fields, enter stuff, click "submit"
# check successfull:
assert self.driver.title == "Added Submission" # redirection works, as expected
## more checks => yes, this is the desired page
# find link for result page:
result_link = self.driver.find_element(By.LINK_TEXT, "click here for your results")
result_link_url = result_link.get_attribute("href")
print(result_link_url) # this is indeed the correct URL
# click link:
time.sleep(10) # wait 10 seconds => more did not help, either
result_link.click()
## now we get the Server Error :-(
print(self.driver.page_source)
I have already tried to use WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.LINK_TEXT, "click here for your results"))).click(), and that doesn't seem to even click.
I know that error 500 mean's the error is on the server side. But before clicking, the server is fine. All the redirections before this step work fine. The URLs also check out. And manually, everything works as expected. I have no idea how to narrow down the problem further.
How can I investigate the reason for this error, and hopefully fix it?
The test creates only a user instance. Is that enough for the view which fails?
You need to get to server traceback to know for sure what's wrong.
from django.test import override_settings
#pytest.mark.django_db
#pytest.mark.usefixtures("chrome_driver_init")
class SubmissionTest(LiveServerTestCase):
#override_settings(DEBUG=True)
def test_adding_submission(self):
...
Take a look at Django: why i can't get the tracebacks (in case of error) when i run LiveServerTestCase tests? for more details.

Selenium chrome driver .click() does not work on particolar website Python

i am trying to log in in a particular website , i fill out email and password and then i click on "login " , but actually it does not login but it redirects me to the home page, i studied the situation and noticed that some websites has a "callback" function, that you can find trought console ,in fact , when i have to register (no login, but sign up) it asks me for captcha, and trought console i found that captcha has a call back function that - if called - it simulates the " register now " button (i easly found this function trought a script that find callback linked to captcha ).
the point is : how can i find this callback function in case of login that has no captcha ? i dont know how to start, any suggestions or guide to study? thats my simply script by the way
driver.get("https://www.streetmachine.com/login")
time.sleep(1)
el=driver.find_element_by_name("email")
el.send_keys(lf[0])
el=driver.find_element_by_name("password")
el.send_keys(lf[1])
time.sleep(3)
el=driver.find_element_by_id("login-form-submit")
driver.execute_script("arguments[0].click();", el)
as you can see the website is the one called in get() , thanks !
You could try to use the "ActionChains"; find the element first and then perform the click.
For example as the following code:
def click_login_button(self, **kargs):
try:
button = WebDriverWait(self.driver, 3).until(
lambda x: x.find_element_by_id("login-form-submit")
)
except TimeoutException:
pass
if not button.is_enabled():
pass
webdriver.ActionChains(self.driver).move_to_element(button).click().perform()
Reference:
Mouse actions in detail, https://www.selenium.dev/documentation/en/support_packages/mouse_and_keyboard_actions_in_detail/

Selenium "Please verify you are a human" Popup in Firefox

I'm curious if anyone has found a work around for handling the random "Please Verify you are human" pop up in FireFox when using Selenium and BeautifulSoup. Currently, it pops up about every 500 or 1,000 URL requests, but I'd love an automated workaround.
My driver is just the default driver = webdriver.Firefox() with selenium. The pop up is a press AND hold button (picture below) which I've just done manually as I've seen it pop up. Any info would be great thanks!
So I've figured out a workaround for this. Since the URL doesn't actually change / redirect when the 'Please verify you are human' popup occurs I've added a step prior to getting the elements with beautifulSoup.
For each URL in the list that is being scraped I do a time.sleep(5.5) to allow URL to fully load or for the verify popup to occur. Then, I interact with the URL and look for the verify indicator. For StockX it works like this: while true, try soup.find('div', class_='page-title').text and if it finds '\nPlease verify you are a human\n' then close browser and sleep (driver.quit() and time.sleep(20)) else scrape elements.
I dont have the full code written up to work but I do know I can detect if its a verify page as mentioned above. Something like this below maybe:
for url in url_list:
for attempt in range(5):
try:
if soup.find('div', class_='page-title').text == '\nPlease verify you are a human\n':
driver.quit()
time.sleep(20)
else:
scrape_everything()
except:
print(f'Hit Verify Page Attempt Num.: {attempt}')
else:
break
else:
continue

How to click an invisible element with selenium?

i used this code to check splinter's clicking button option:
from splinter import Browser
with Browser() as browser:
# Visit URL
url = "http://www.google.com"
browser.visit(url)
browser.fill('q', 'splinter - python acceptance testing for web applications')
# Find and click the 'search' button
button = browser.find_by_name('btnG')
# Interact with elements
button.click()
if browser.is_text_present('splinter.readthedocs.org'):
print("Yes, the official website was found!")
else:
print("No, it wasn't found... We need to improve our SEO techniques")
and i got exception:
Element is not currently visible ans so may not be interacted.
waiting for the browser is not the solution (becuase i made sleep method for long time and still doesnt work).
this is sample code shown in https://splinter.readthedocs.org/en/latest/#sample-code , but is doesnt work for me
If you want to wait for an element to become invisible, you can use wait function:
wait = WebDriverWait(self.driver, 30)
wait.until(EC.invisibility_of_element_located((By.XX, "something")))

Categories