滑块自动验证实现

目录

一、实现思路

1、把滑块移动到底

2、控制滑动速度,模拟手动滑动的情况

二、实现代码示例

三、示例函数分析

1、函数总体功能

2、函数定义和参数

3、函数体内部结构

四、总结


最近写的RPA脚本经常遇到登录时,需要进行滑块验证的情况,分享下如何处理这种情况,以某个网站为例:

一、实现思路

滑块验证要做的有两点:1、把滑块移动到底;2、控制滑动速度,模拟手动滑动的情况。

1、把滑块移动到底

为了实现第一点,我们首先需要获取滑块。先打开控制台,获取滑块元素的id及相关信息。

这里我们可以看到,滑块本身的id为 nc_1_n1z,利用document?.querySelector("#nc_1_n1z")就能获取到滑块的DOM。另外,还需要获取滑块组件的宽度,直接选中元素看他的宽度就可以。这里的滑块组件宽度为300px。

接下来,我们可以调用getBoundingClientRect()方法来从代码层面获取滑块的宽高。

并用相应变量接收宽高的值。

  • getBoundingClientRect()是一个 JavaScript 中的 DOM API,用于获取元素相对于浏览器视口(viewport)的位置和大小信息。它返回一个DOMRect对象,这个对象包含了元素的left(元素左边界距离视口左边界的距离)、top(元素上边界距离视口上边界的距离)、right(元素右边界距离视口左边界的距离)、bottom(元素下边界距离视口上边界的距离)、width(元素的宽度)和height(元素的高度)等属性。

现在我们已经有了滑块DOM及滑块的宽高值。只需要定义鼠标按下mousedown、鼠标移动mousemove、鼠标松开mouseup事件并调用即可。

2、控制滑动速度,模拟手动滑动的情况

手动滑动滑块通常不是匀速,一般开始慢,中间快,结尾慢。因此,我们利用0.5x^3来实现模拟前半段运动,利用0.5((x - 2)^3 + 2)来模拟后半段运动。示例:

javascript 复制代码
function easeInOutCubic(t) {
    t *= 2;
    if (t < 1) return 0.5 * t * t * t;
    t -= 2;
    return 0.5 * (t * t * t + 2);
  }

除了模拟运动过程,还要指定运动时间,给个合理的时间来完成整个滑动过程。

二、实现代码示例

javascript 复制代码
/*
   *  验证滑块滑动
   */
 function sliderMoveByAnimation(targetElement, distance = 0, duration = 400) {
  console.log(targetElement)
  const rect = targetElement.getBoundingClientRect();
  const startMouseX = rect.left + rect.width / 2;
  const startMouseY = rect.top + rect.height / 2;

  function easeInOutCubic(t) {
    t *= 2;
    if (t < 1) return 0.5 * t * t * t;
    t -= 2;
    return 0.5 * (t * t * t + 2);
  }
  const mouseDownEvent = new MouseEvent("mousedown", { bubbles: true, clientX: startMouseX, clientY: startMouseY });
  targetElement.dispatchEvent(mouseDownEvent);
  const startTime = performance.now();
  function animate() {
    const currentTime = performance.now();
    const elapsed = currentTime - startTime;
    if (elapsed < duration) {
      const progress = elapsed / duration;
      const newPosition = distance * easeInOutCubic(progress);
      console.log(progress)
      const mouseMoveEvent = new MouseEvent("mousemove", { bubbles: true, clientX: startMouseX + newPosition, clientY: startMouseY });
      targetElement.dispatchEvent(mouseMoveEvent);
      requestAnimationFrame(animate);
    } else {
      const mouseUpEvent = new MouseEvent("mouseup", { bubbles: true, clientX: startMouseX + distance, clientY: startMouseY });
      targetElement.dispatchEvent(mouseUpEvent);
    }
  }
  animate();
};

三、示例函数分析

1、函数总体功能

  • 这里定义了一个名为sliderMoveByAnimation的函数,用于通过动画方式移动滑块(slider)。它模拟了鼠标按下、移动和抬起的操作来实现滑块的移动。

2、函数定义和参数

  • 函数定义如下:
javascript 复制代码
function sliderMoveByAnimation(targetElement, distance = 0, duration = 400) {
  // 函数体
}
  • targetElement:要移动的目标元素。
  • distance:滑块要移动的距离,默认为 0。
  • duration:动画的持续时间,默认为 400 毫秒。

3、函数体内部结构

  • 获取目标元素的位置信息
javascript 复制代码
const rect = targetElement.getBoundingClientRect();
const startMouseX = rect.left + rect.width / 2;
const startMouseY = rect.top + rect.height / 2;

首先,通过getBoundingClientRect方法获取目标元素的边界矩形信息。

然后,计算出鼠标起始位置(startMouseXstartMouseY),这是通过将元素的中心位置作为鼠标的起始位置来计算的

  • 定义缓动函数
javascript 复制代码
function easeInOutCubic(t) {
  t *= 2;
  if (t < 1) return 0.5 * t * t * t;
  t -= 2;
  return 0.5 * (t * t * t + 2);
}

这个函数easeInOutCubic是一个缓动函数,用于计算动画的进度。它根据传入的时间参数t(0 到 1 之间)计算出一个经过缓动处理的值,使得动画在开始和结束时速度较慢,中间速度较快。利用0.5x^3来实现模拟前半段运动,利用0.5((x - 2)^3 + 2)来模拟后半段运动。

  • 模拟鼠标按下事件
javascript 复制代码
const mouseDownEvent = new MouseEvent("mousedown", { bubbles: true, clientX: startMouseX, clientY: startMouseY });
targetElement.dispatchEvent(mouseDownEvent);

创建一个mousedown鼠标按下事件,并将其触发在目标元素上,模拟鼠标按下操作。

  • 开始动画循环
javascript 复制代码
const startTime = performance.now();
function animate() {
  const currentTime = performance.now();
  const elapsed = currentTime - startTime;
  if (elapsed < duration) {
    const progress = elapsed / duration;
    const newPosition = distance * easeInOutCubic(progress);
    console.log(progress);
    const mouseMoveEvent = new MouseEvent("mousemove", { bubbles: true, clientX: startMouseX + newPosition, clientY: startMouseY });
    targetElement.dispatchEvent(mouseMoveEvent);
    requestAnimationFrame(animate);
  } else {
    const mouseUpEvent = new MouseEvent("mouseup", { bubbles: true, clientX: startMouseX + distance, clientY: startMouseY });
    targetElement.dispatchEvent(mouseUpEvent);
  }
}
animate();

首先,记录动画开始时间startTime

animate函数中:

计算当前时间currentTime和已经过去的时间elapsed

如果elapsed小于duration(动画未完成):

计算动画进度progress

根据progressdistance计算滑块的新位置newPosition

创建并触发mousemove鼠标移动事件,更新滑块位置。

通过requestAnimationFrame请求下一帧动画。

如果elapsed大于等于duration(动画完成):

创建并触发mouseup鼠标抬起事件

四、总结

按照上述步骤,可以应对绝多数滑块验证的场景。可以直接复制那个示例函数,然后只需要传入滑块DOM,定义滑动距离和时间就好了。

另外,需要注意有些登录框放在iframe里,获取滑块DOM的时候需要先拿到iframe,然后从iframe里面获取滑块,例如

javascript 复制代码
document.querySelector('iframe:is(#alibaba-login-box)')?.contentWindow.document.querySelector("#nc_1_n1z")

如果有特殊情况,欢迎在评论区探讨

相关推荐
中微子4 分钟前
JavaScript 防抖与节流:从原理到实践的完整指南
前端·javascript
天天向上102419 分钟前
Vue 配置打包后可编辑的变量
前端·javascript·vue.js
芬兰y35 分钟前
VUE 带有搜索功能的穿梭框(简单demo)
前端·javascript·vue.js
好果不榨汁42 分钟前
qiankun 路由选择不同模式如何书写不同的配置
前端·vue.js
小蜜蜂dry42 分钟前
Fetch 笔记
前端·javascript
拾光拾趣录43 分钟前
列表分页中的快速翻页竞态问题
前端·javascript
小old弟44 分钟前
vue3,你看setup设计详解,也是个人才
前端
Lefan1 小时前
一文了解什么是Dart
前端·flutter·dart
Patrick_Wilson1 小时前
青苔漫染待客迟
前端·设计模式·架构
vvilkim1 小时前
Nuxt.js 全面测试指南:从单元测试到E2E测试
开发语言·javascript·ecmascript