Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to let my script slide a button to the right

I've written a script in python in combination with selenium to log in to a website. The thing is my script sometimes successfully gets logged in but most of the times it comes across a slider which is meant to press and slide to the right.

  • Website link

  • Image of that slider: enter image description here

How can I let my script slide that button to the right?

I've tried with:

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def sign_in():
    driver.get("https://login.aliexpress.com/")
    wait.until(EC.frame_to_be_available_and_switch_to_it(wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#alibaba-login-box")))))
    wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "input#fm-login-id"))).send_keys("someEmail")
    wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "input#fm-login-password"))).send_keys("somePassword")
    wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "button[class$='password-login']"))).click()

    #the following line is for handling the slider but it doesn't do anything

    item = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".nc_wrapper .btn_slide")))
    ActionChains(driver).move_to_element(item).perform()

if __name__ == '__main__':
    driver = webdriver.Chrome()
    wait = WebDriverWait(driver,10)
    sign_in()

Html elements connected to that slider:

<div id="nc_1_n1t" class="nc_scale">
<div id="nc_1__bg" class="nc_bg" style="width: 0px;"></div>
<span id="nc_1_n1z" class="nc_iconfont btn_slide" data-spm-anchor-id="0.0.0.i1.3f9579f4qCwuHp" style="left: 0px;"></span>
<div id="nc_1__scale_text" class="scale_text slidetounlock"><span class="nc-lang-cnt" data-nc-lang="_startTEXT">Please slide to verify</span></div>
<div id="nc_1_clickCaptcha" class="clickCaptcha" style="top: -118px; height: 235px;">
<div class="clickCaptcha_text">
<b id="nc_1__captcha_text" class="nc_captch_text"></b>
<i id="nc_1__btn_2" class="nc_iconfont nc_btn_2 btn_refresh"></i>
</div>
<div class="clickCaptcha_img"></div>
<div class="clickCaptcha_btn"></div>
</div>
<div id="nc_1_imgCaptcha" class="imgCaptcha" style="top: -118px; min-height: 290px; height: 189px;">
<div class="imgCaptcha_text"><input id="nc_1_captcha_input" maxlength="6" type="text" style="ime-mode:disabled"></div>
<div class="imgCaptcha_img" id="nc_1__imgCaptcha_img"></div>
<i id="nc_1__btn_1" class="nc_iconfont nc_btn_1 btn_refresh" onclick="document.getElementById('nc_1__imgCaptcha_img').children[0].click()"></i>
<div class="imgCaptcha_btn">
<div id="nc_1__captcha_img_text" class="nc_captcha_img_text"></div>
<div id="nc_1_scale_submit" class="nc_scale_submit"></div>
</div>
</div>
<div id="nc_1_cc" class="nc-cc"></div>
<i id="nc_1__voicebtn" tabindex="0" role="button" class="nc_voicebtn nc_iconfont" style="display:none"></i>
<b id="nc_1__helpbtn" class="nc_helpbtn"><span class="nc-lang-cnt" data-nc-lang="_learning">help</span></b>
</div>
like image 554
MITHU Avatar asked Oct 20 '25 16:10

MITHU


1 Answers

I'm unable to get the slider to display on the website linked in the question, so I have provided a solution using another site that has a slider element (I'm assuming the functionality is similar to the one on the aliexpress website).

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait

# Instantiate objects
driver = webdriver.Chrome()
actions = ActionChains(driver)

# Load page and fill in input elements
driver.get("http://kthornbloom.com/slidetosubmit/")
driver.find_element(By.NAME, "name").send_keys("Fred")
driver.find_element(By.NAME, "email").send_keys("[email protected]")

# Find slider elements
slider_container = driver.find_element(By.CSS_SELECTOR, ".slide-submit")
slider = driver.find_element(By.CSS_SELECTOR, ".slide-submit-thumb")

# Perform sliding action
actions.move_to_element(slider).click_and_hold().move_by_offset(slider_container.size['width'], 0).release().perform()

# Browser intentionally left open so that you can see what happened when the test was run!

The key part here, is the Perform sliding action line. We have to identify two specific elements:

  1. The element that we are going to slide
  2. The container that holds this element

Once we have found both of these elements, we use the actions class to click and hold the element we need to slide and then we slide it the width of the containing element along the x axis (as shown using slider_container.size['width']), without changing the y axis.

This should fix your sliding problem, however you will have another problem, you need to work out if the slider was displayed, or you were logged into the website. To do that you are going to need an Expected condition that checks for the existence of 2 elements:

  1. The slider.
  2. An element you would expect to see when you have successfully logged in.

If the element you would expect to see when you log in is shown, you don't need to do anything. If the slider is shown, you will need to perform the above logic to slide the bar across.

*Edit*

To improve on this a bit more you can put the sliding code into an ExpectedCondition like so:

class wait_for_element_while_verifying_slider(object):

    def __init__(self, locator, slider_container_locator, slider_locator):
        self.locator = locator
        self.slider_container_locator = slider_container_locator
        self.slider_locator = slider_locator

    def __call__(self, _driver):
        try:
            return _driver.find_element(*self.locator)
        except (NoSuchElementException, StaleElementReferenceException):
            container = _driver.find_elements(*self.slider_container_locator)
            slider = _driver.find_elements(*self.slider_locator)
            if len(container) > 0 and len(slider) > 0:
                actions = ActionChains(_driver)
                actions.move_to_element(slider[0]).click_and_hold().move_by_offset(container[0].size['width'], 0).release().perform()

        return False

This will search for an element that you expect to be shown when you log in. If the element that you would expect to see when you have successfully logged in is not shown, it will then try and locate the slider elements and interact with them to process the slide verification. Note that once it tries to perform the slide verification the Expected Condition will return False which will force it to check to see if the expected logged in element is displayed again.

You can use it in your code like this:

# Instantiate objects
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 10)

# Load page and fill in input elements
driver.get("http://kthornbloom.com/slidetosubmit/")
driver.find_element(By.NAME, "name").send_keys("Fred")
driver.find_element(By.NAME, "email").send_keys("[email protected]")

# Define slider elements and element that will be shown when you successfully log in
SLIDER_CONTAINER = (By.CSS_SELECTOR, ".slide-submit")
SLIDER = (By.CSS_SELECTOR, ".slide-submit-thumb")
ELEMENT_TO_FIND = (By.XPATH, "//div[.=\"Looks Like You're Human!\"]")

# Invoke the explicit wait that will deal with the slider if it is displayed
wait.until(wait_for_element_while_verifying_slider(ELEMENT_TO_FIND, SLIDER_CONTAINER, SLIDER))

The example above uses the same example website as above. To make it timeout you can change ELEMENT_TO_FIND to something that doesn't exist. To make it pass without sliding you can modify ELEMENT_TO_FIND to be:

ELEMENT_TO_FIND = (By.XPATH, "//div[.=\"Slide To Submit\"]")

Using the code you have provided in your comment I would expect the following to work on the aliexpress website:

# Define slider elements and element that will be shown when you successfully log in
SLIDER_CONTAINER = (By.CSS_SELECTOR, ".nc-lang-cnt")
SLIDER = (By.CSS_SELECTOR, ".nc_wrapper .btn_slide")
ELEMENT_TO_FIND = (By.ID, "search-key")

# Invoke the explicit wait that will deal with the slider if it is displayed
wait.until(wait_for_element_while_verifying_slider(ELEMENT_TO_FIND, SLIDER_CONTAINER, SLIDER))
like image 151
Ardesco Avatar answered Oct 23 '25 05:10

Ardesco