Невозможно позволить моему сценарию сдвинуть кнопку вправо - PullRequest
3 голосов
/ 30 июня 2019

Я написал скрипт на python в сочетании с селеном для входа на сайт.Дело в том, что мой скрипт иногда успешно входит в систему, но в большинстве случаев он сталкивается с ползунком, который предназначен для нажатия и перемещения вправо.

Как я могу позволить моемуСкрипт сдвинуть эту кнопку вправо?

Я пробовал с:

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-элементы, связанные с этим ползунком:

<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>

Ответы [ 3 ]

5 голосов
/ 09 июля 2019

Мне не удается отобразить ползунок на веб-сайте, связанном в вопросе, поэтому я предоставил решение, используя другой сайт с элементом ползунка (я предполагаю, что функциональность аналогична функциональности на Aliexpress веб-сайт).

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("fred@example.com")

# 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!

Ключевой частью здесь является строка Perform sliding action. Мы должны выделить два конкретных элемента:

  1. Элемент, который мы собираемся скользить
  2. Контейнер, содержащий этот элемент

Как только мы нашли оба этих элемента, мы используем класс actions, чтобы щелкнуть и удерживать элемент, который нам нужно сдвинуть, а затем передвинем его на ширину содержащего элемента вдоль оси x (как показано с помощью slider_container.size['width']) , без изменения оси Y.

Это должно решить вашу проблему со скольжением, однако у вас будет другая проблема, вам нужно решить, был ли отображен слайдер или вы вошли на веб-сайт. Для этого вам понадобится ожидаемое условие, которое проверяет наличие 2 элементов:

  1. Слайдер.
  2. Элемент, который вы ожидаете увидеть после успешного входа в систему.

Если отображается элемент, который вы ожидаете увидеть при входе в систему, вам не нужно ничего делать. Если ползунок показан, вам нужно будет выполнить приведенную выше логику, чтобы переместить полосу.

* Редактировать *

Чтобы немного улучшить ситуацию, вы можете поместить скользящий код в ExpectedCondition следующим образом:

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

При этом будет выполнен поиск элемента, который вы ожидаете увидеть при входе в систему. Если элемент, который вы ожидаете увидеть при успешном входе в систему, не отображается, он попытается найти элементы ползунка и взаимодействовать с ними. с ними, чтобы обработать проверку слайдов. Обратите внимание, что, как только он попытается выполнить проверку слайдов, ожидаемое условие вернет значение False, что заставит его проверить, отображается ли ожидаемый вошедший в систему элемент снова.

Вы можете использовать его в своем коде так:

# 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("fred@example.com")

# 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))

В приведенном выше примере используется тот же пример веб-сайта, что и выше. Чтобы сделать это тайм-аут, вы можете изменить ELEMENT_TO_FIND на то, что не существует. Чтобы он прошел без скольжения, вы можете изменить ELEMENT_TO_FIND на:

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

Используя код, который вы указали в комментарии, я ожидаю, что на сайте aliexpress будет работать следующее:

# 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))
1 голос
/ 05 июля 2019

Пример кода (в Java) для работы ползунка слева направо ниже.

Actions slider=new Actions(driver);
slider.clickAndHold("xpath of slider");
slider.movebyoffset(x,y).build.perform(); 

вместо 'x' и 'y' вы можете указать фактическое значение смещения в соответствии с вашим приложением.

1 голос
/ 03 июля 2019

Попробуйте использовать Действия Ниже приведен код c # для справки

//following code will click and hold the slider
string Xpath=""; //set xpath for desired element to be click and hold
Actions clickHold = new Actions(driver);
IWebElement element = driver.FindElement(By.XPath(Xpath));
clickHold.ClickAndHold(element).Perform();

удерживая ползунок, попробуйте переместить его в нужное значение смещения

int x = 100; 
int y = 100;
Actions moveOffset = new Actions(driver);
moveOffset.MoveByOffset(x,y).Perform(); //set your suitable (x,y) offset value
...