使用Python Selenium 实现拖拽动作时动作不流畅

3 篇文章 0 订阅
2 篇文章 0 订阅

出现了标题问题,没有达到预期的效果。上网也查找一些有没有相关的内容的说明和解决方案,但是大多数解决方案与我这个情况好像不相关。特此将我自己的解决方案记录下来,供人参考。着急可以直接看 结果

环境

  • macOS 10.14.4
  • python 3.7.2
  • selenium 3.141.0
  • chrome 76.0.3809.132(64位)
  • webdriver是和chrome相匹配的版本

问题

最近由于工作原因,需要自动登录jd的页面。但是最近发现有时登录时,经常弹出滑块让你进行拖拽验证。理论上直接破解js的加密函数是可以做到的,但是太费时间了。处于简单的目的,于是使用 python 的 selenium 库进行用户模拟操作处理。

在一切就绪后,发现了一个问题,就是拖拽的动作很不流畅,感觉是一顿一顿的移动,根本无法达到“拟人”的操作效果。

查看主要拖拽部分的代码,感觉也没有什么问题。主要代码如下:

# 选中要拖拽的元素
slider_el = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'xxx')))
# 然后‘点击并按住’。
ActionChains(self.driver).click_and_hold(slider_el).perform()

# tracks 是生成一些列的X轴位移距离数组。例如:[0,0,0,1,1,1,2,5,7, ...]
# 实现正向滑动
for track in tracks:
    yoffset_random = random.uniform(-2, 4)
    # xoffset、yoffset在函数内部都会被转为整数的。
    ActionChains(self.driver).move_by_offset(xoffset=track, yoffset=yoffset_random).perform()

PS:这里有一些网站可能可能因为元素设计的原因,导致你获取到元素后,直接click_and_hold拖拽失效。可以尝试让让焦点稍微位移几个元素,然后再尝试后续动作。

效果如下:
拖拽(抖动)示例
拖拽(抖动)示例2
虽然在示例中,第一次验证通过了(真的是碰巧)。但是可以发现在整个的运动过程中,每次移动后都会出现一个短暂的停顿效果,尤其在速度比较快的时候感觉特别明显。

解决

由于没能找到别人的解决方法,只能自己动手找找了。看文档没发现什么还能传递的特殊函数可以控制。那么就先从拖动方法的源码看起。

1. 外部调用的移动鼠标的函数

方法 ActionChains(self.driver).move_by_offset(x, y)
文件 /selenium/webdriver/common/action_chains.py

def move_by_offset(self, xoffset, yoffset):
    """
    Moving the mouse to an offset from current mouse position.

    :Args:
     - xoffset: X offset to move to, as a positive or negative integer.
     - yoffset: Y offset to move to, as a positive or negative integer.
    """
    if self._driver.w3c:
        self.w3c_actions.pointer_action.move_by(xoffset, yoffset)
        self.w3c_actions.key_action.pause()
    else:
        self._actions.append(lambda: self._driver.execute(
            Command.MOVE_TO, {
                'xoffset': int(xoffset),
                'yoffset': int(yoffset)}))
    return self

2. 第一步就是调用移动鼠标的函数的实现

方法 self.w3c_actions.pointer_action.move_by(xoffset, yoffset)
文件 /selenium/webdriver/common/actions/pointer_actions.py

def move_by(self, x, y):
    self.source.create_pointer_move(origin=interaction.POINTER, x=int(x), y=int(y))
    return self

3. 上一步它初始化了一个类,并调用这个的类的具体实现函数

方法 self.source.create_pointer_move(origin=interaction.POINTER, x=int(x), y=int(y))
文件 /selenium/webdriver/common/actions/pointer_input.py

class PointerInput(InputDevice):
	
    DEFAULT_MOVE_DURATION = 250

    def __init__(self, kind, name):
        super(PointerInput, self).__init__()
        if (kind not in POINTER_KINDS):
            raise InvalidArgumentException("Invalid PointerInput kind '%s'" % kind)
        self.type = POINTER
        self.kind = kind
        self.name = name

    def create_pointer_move(self, duration=DEFAULT_MOVE_DURATION, x=None, y=None, origin=None):
        action = dict(type="pointerMove", duration=duration)
        action["x"] = x
        action["y"] = y
        if isinstance(origin, WebElement):
            action["origin"] = {"element-6066-11e4-a52e-4f735466cecf": origin.id}
        elif origin is not None:
            action["origin"] = origin

        self.add_action(action)
    ...

到这里我们找到拖拽这个动作的根源了。
def create_pointer_move(self, duration=DEFAULT_MOVE_DURATION, x=None, y=None, origin=None) 该方法有4个参数,其中x,y是我们传递的,origin是在上一层方法传入的参数,而 duration是一个默认值,且没有在class初始化时传入,也没有通过方法传入。DEFAULT_MOVE_DURATION = 250 根据名字我猜到这个参数应该就是用来控制每次执行移动的消耗实现。根据测试其值应该是毫秒值。

那么我们只需要修改它应该就可以减少每次执行的时间,来增加拖动的流畅度。我是直接在源码里修改这个值的大小测试的。最后结果如下图:

调整后示例
调整后示例2
我调整到50左右,反正从我这里看,这个拖动可以算作是流畅了,我的目的也达到了。测试的时候,通过率基本能达到9成左右。超过5成测试都是一次性通过的。

结果

修改 selenium 源码 /selenium/webdriver/common/actions/pointer_input.py 文件中的 DEFAULT_MOVE_DURATION = 250 的值,到50左右,这个值应该是用于控制动作的执行时间。

最后附上项目地址:
https://github.com/RysisLiang/Trial_Jigsaw

本内容仅供学习交流讨论,非商业性质。如果有其它的解决方案,欢迎留言。

  • 20
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
使用Python Selenium进行GUI自动化测试可以通过以下步骤开始: 1. 首先,您需要安装PythonSelenium库。您可以使用pip命令在命令行中执行以下命令来安装Selenium库:pip install selenium。 2. 安装完成后,您还需要下载并安装适用于您浏览器的WebDriver。根据您的浏览器类型,您可以从以下链接下载适用于不同浏览器的WebDriver: - Chrome:https://sites.google.com/a/chromium.org/chromedriver/downloads - Firefox:https://github.com/mozilla/geckodriver/releases - Safari:https://webkit.org/blog/6900/webdriver-support-in-safari-10/ - Edge:https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ 3. 下载并安装适当的WebDriver之后,您可以导入Selenium库并开始编写自动化测试脚本。 4. 使用SeleniumWebDriver类创建一个浏览器实例,如下所示: driver = webdriver.Chrome()(如果使用Chrome浏览器) driver = webdriver.Firefox()(如果使用Firefox浏览器) driver = webdriver.Safari()(如果使用Safari浏览器) driver = webdriver.Edge()(如果使用Edge浏览器) 5. 接下来,您可以使用WebDriver实例访问和操作网页元素。可以使用不同的定位器方法(如id、name、class name、xpath等)来定位和操作页面元素。例如,您可以使用find_element_by_id方法来查找具有特定id的元素。 WebDriverWait(driver, 10).until(lambda driver: driver.find_element_by_id("kw")) 6. 在找到元素后,您可以使用不同的方法来执行各种操作,例如输入文本、点击按钮等。 7. 最后,您可以关闭浏览器实例,完成自动化测试。 driver.quit() 以上是使用Python Selenium进行GUI自动化测试的基本步骤和方法。您可以根据具体需求和场景进行详细的脚本编写和测试执行。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [python-selenium:使用Python Selenium进行GUI自动化测试](https://download.csdn.net/download/weixin_42157188/18321191)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [python selenium firefox使用详解](https://download.csdn.net/download/weixin_38639615/12864153)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Python Selenium使用](https://blog.csdn.net/fz1992092500/article/details/118379817)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值