前两天需要自动化登录一个商城的后台 用的是playwright 没有用selenium 中间出了一个滑块验证 现阶段playwright教程不是太多,自己做移动的时候各种找,费劲巴拉的。现在自己整出来了就记录一下吧!
上流程,首先缺口获取
#没有用过opencv的cv2导入报错的 可以安装 #pip install opencv-python import cv2 def get_notch_location(hx, bg): ''' 根据文件进行识别 :param hx: 滑块图片的文件路径 :param bg: 背景图片的文件路径 :return: ''' bg_img = cv2.imread(hx,0) tp_img = cv2.imread(bg,0) # 读取到两个图片,进行灰值化处理 img = cv2.imread(bg) # 读取图片画框直观可以看到,上边是灰度的所以重新打开一个原图 res = cv2.matchTemplate(_tran_canny(bg_img), _tran_canny(tp_img), cv2.TM_CCOEFF_NORMED) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) top_left = max_loc[0] # 横坐标 # 展示圈出来的区域 x, y = max_loc # 获取x,y位置坐标 w, h = bg_img.shape[::-1] # 宽高 #矩形画图 cv2.rectangle(img, (x, y), (x + w, y + h), (0,0,255), 2) #显示 cv2.imshow('Show', name) cv2.waitKey(0) cv2.destroyAllWindows() #这个是滑块要移动的距离 return top_left
测试一下(包括肉眼看不太清楚的同样可以不得不说opencv的强大)
测试图片
https://img2020.cnblogs.com/blog/1776613/202201/1776613-20220104104600734-2080308296.jpg
https://img2020.cnblogs.com/blog/1776613/202201/1776613-20220104110557885-1084215972.jpg
下边轨迹移动(其实就是移动距离分了好多步)
#有的检测移动速度的 如果匀速移动会被识别出来,来个简单点的 渐进 def get_track(distance): # distance为传入的总距离 # 移动轨迹 track = [] # 当前位移 current = 0 # 减速阈值 mid = distance * 4 / 5 # 计算间隔 t = 0.2 # 初速度 v = 1 while current < distance: if current < mid: # 加速度为2 a = 4 else: # 加速度为-2 a = -3 v0 = v # 当前速度 v = v0 + a * t # 移动距离 move = v0 * t + 1 / 2 * a * t * t # 当前位移 current += move # 加入轨迹 track.append(round(move)) return track
接下来就是重点了(说是重点简单的雅痞)
#移动滑块 #首先咱们的找到要移动的东西吧 s = self.page.wait_for_selector('//div[@class="_3CvVPX _3gznAC _3BUN_s"]',strict=True) #找到这个元素再当前页面的坐标(这个会返回一个字典里边四个数字) box = s.bounding_box() #移动鼠标到上边元素的中心(上边四个参数用途来了) self.page.mouse.move(box["x"] + box["width"] / 2, box["y"] + box["height"] / 2) #按下鼠标(这个不多说) self.page.mouse.down() #这里获取到x坐标中心点位置 x = box["x"] + box["width"] / 2 #这个把缺口获取到的长度放到轨迹加工一下得到一个轨迹 tracks = get_track(top_left) for track in tracks: #循环鼠标按照轨迹移动 #strps 是控制单次移动速度的比例是1/10 默认是1 相当于 传入的这个距离不管多远0.1秒钟移动完 越大越慢 self.page.mouse.move(x + track, 0,steps=10) x += track #移动结束鼠标抬起 self.page.mouse.up()
当鼠标抬起呢一刻 你就可以心里石头落地了,他过了
控制好速度 反正我这基本都能过
下边给一个html 可以自己测试的页面(其实扒拉别人的)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div class="box"> <div class="btn">>></div> <p class="text">拖动滑块验证</p> <div class="bg"></div> </div> <style> * { margin: 0; padding: 0; background-color: #ffffff; } .box { width: 500px; height: 60px; position: relative; left: 50%; margin-left: -250px; margin-top: 50px; background: #eae4e4; display: flex; align-items: center; -webkit-user-select:none; -moz-user-select:none; -ms-user-select:none; user-select:none; } .btn { height: 100%; width: 60px; background: #fbf5f5; box-sizing: border-box; border: 2px solid #cecaca; position: absolute; left: 0; top: 0; display: flex; align-items: center; justify-content: center; font-size: 25px; color: #d5d4d4; z-index: 999; -webkit-user-select:none; -moz-user-select:none; -ms-user-select:none; user-select:none; } .btn:hover { cursor:pointer; } .text { font-size: 20px; position: absolute; left: 50%; margin-left: -60px; background-color: transparent; z-index: 2; } .bg { height: 100%; position: absolute; background-color: #4cbb42; z-index: 1; } </style> <script> window.onload = function () { // 封装-选择器,内部可以做兼容性 function querySelect(name) { return document.querySelector(name) } // 验证成功 // 验证失败 // 触发事件 onmousedown按下 onmousemove移动 onmouseup松开 let btn = querySelect('.btn') // 滑块 对IE6/7 有兼容性问题 let box = querySelect('.box') // box let text = querySelect('.text') // 文字 let bg = querySelect('.bg') // 背景 btn.onmousedown = (eventDown) => { // event.clientX;clientY 鼠标当前X轴Y轴坐标 let downX = eventDown.clientX console.log(downX) document.onmousemove = (eventMove) => { // 移动的X坐标 - 按下的X坐标 let moveX = eventMove.clientX - downX console.log(eventDown.clientX) console.log(moveX) let boxWidth = box.offsetWidth let btnWidth = btn.offsetWidth if (moveX >= 0 && moveX <= (boxWidth - btnWidth)) { // 可移动的范围 btn.style.left = moveX + 'px' // 滑块绝对定位 bg.style.width = moveX + 'px' // 设备背景的宽度 } if (moveX >= (boxWidth - btnWidth)) { btn.style.left = (boxWidth - btnWidth) + 'px' // 滑块绝对定位 bg.style.width = (boxWidth - btnWidth) + 'px' // 设备背景的宽度 // 文字提醒 text.innerText = '验证成功' text.style.color = '#fff' // 事件清除-按下、移动 btn.onmousedown = null document.onmousemove = null btn.onmouseup = null } } } btn.onmouseup = (eventUp) => { // 松开后回到原点 // 清除移动事件 console.log('鼠标抬起') btn.style.left = 0 + 'px' bg.style.width = 0 + 'px' document.onmousemove = null } } </script> </body> </html>