【问题标题】:Unable to let my script slide a button to the right无法让我的脚本向右滑动按钮
【发布时间】:2019-11-11 10:42:35
【问题描述】:

我在 python 中结合 selenium 编写了一个脚本来登录网站。问题是我的脚本有时会成功登录,但大多数时候它会遇到一个滑块,该滑块旨在按下并向右滑动。

如何让我的脚本将该按钮向右滑动?

我试过了:

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>

【问题讨论】:

  • 其他 action chain 功能包括鼠标按下 (click_and_hold())、鼠标移动 (move_by_offset()) 和鼠标向上 (release()) 操作。
  • 是否可以共享登录的测试用户名和密码。
  • 也许你可以提供一个我可以合作的网站的网址并确保一个可行的解决方案?
  • 从不为我显示滑块:(
  • 当您连续执行脚本几次@Ardesco 时会显示该滑块。

标签: python python-3.x selenium selenium-webdriver web-scraping


【解决方案1】:

我无法让滑块显示在问题中链接的网站上,因此我提供了使用另一个具有滑块元素的网站的解决方案(我假设该功能类似于速卖通上的功能)网站)。

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. 容纳此元素的容器

找到这两个元素后,我们使用动作类单击并按住我们需要滑动的元素,然后沿 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\"]")

使用您在评论中提供的代码,我希望以下内容可以在速卖通网站上运行:

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

【讨论】:

  • 问题已更新以尝试帮助您解决这个问题。你也许可以让它更干净,但我会把它留给你:)
【解决方案2】:

从左到右进行滑块操作的示例代码(java中)如下。

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

您可以根据您的应用提供实际的偏移值来代替“x”和“y”。

【讨论】:

    【解决方案3】:

    尝试使用Actions 下面是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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多