开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看详情,今天分享一下滑块验证使用自动化测试时有些网站会使用滑块来阻止,所以如何解决滑块问题已经成为自动化测试不可或缺的,今天以网易易盾网站的滑块举例:dun.163.com/trial/sense
一、首先分享一下我的解决思路:
1.首先打开网页分析找出滑块的位置,使用自动化的方法去拖动 2.有了思路就开始分解实现:
(1)滑块和滑块背景的获取 要获取到滑块的图片,还要获取到背景图片。由于滑块的图片每次刷新之后都是会变的,所以要实时的获取到滑块和背景图的位置,这个时候就需要使用requests获取到图片并保存在本地。 ps:这里有人会困惑,直接用截图不是更好,做出这个滑块的人早也想到了,截图就会发现获取到的并不是真正的滑块,只是获取到了滑块那个位置的一个正方形的图片,并不是真正意义上的滑块。
(2)读取滑块和背景图片 这里使用的是OpenCV对已经保存图片进行灰度处理,灰度处理的目的是为了让让两个图片更容易找出相似处,灰度处理之后使用OpenCV中的cv2.matchTemplate方法寻找出两个图片的相似之处
(3)获取坐标并拖动 使用numpy获取到滑块的坐标,然后使用xpath进行定位,最后使用ActionChains进行拖动 此外,因为滑块的拖动不是一次性就能成功的,所以要注意添加跳出循环的条件来保证最后的成功, 代码如下:
import requests
import time
import cv2
import numpy as np
from selenium.webdriver import ActionChains
driver =webdriver.Chrome(r"chromedriver.exe的位置")
driver.get('https://dun.163.com/trial/sense')
# 点击进入滑块界面
driver.find_element_by_xpath('/html/body/main/div[1]/div/div[2]/div[2]/ul/li[2]').click()
time.sleep(1)
# 点击完成验证
driver.find_element_by_xpath('/html/body/main/div[1]/div/div[2]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[3]/div/div/div[1]/div[1]/span').click()
time.sleep(3)
while True:
# 获取两张图片
url_s = driver.find_element_by_class_name('yidun_jigsaw').get_attribute('src')
url_b = driver.find_element_by_class_name('yidun_bg-img').get_attribute('src')
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36'
}
res_s = requests.get(url_s,headers=headers)
data_s = res_s.content
res_b = requests.get(url_b,headers=headers)
data_b = res_b.content
# 保存图片
with open('pic_s.png','wb')as f:
f.write(data_s)
with open('pic_b.png','wb')as f:
f.write(data_b)
# 使用opencv读取两张图片
simg = cv2.imread('pic_s.png')
bimg = cv2.imread('pic_b.png')
# 灰度处理,降低偏差
s_img = cv2.cvtColor(simg,cv2.COLOR_BGR2GRAY)
b_img = cv2.cvtColor(bimg,cv2.COLOR_BGR2GRAY)
# 保存两张灰度处理的图片
cv2.imwrite('hui_simg.png',s_img)
cv2.imwrite('hui_bimg.png',b_img)
# 处理滑块图片,保存有效部分
s_img = s_img[s_img.any(1)]
# opencv的匹配算法,匹配模块寻找两张图片的相似之处
result = cv2.matchTemplate(b_img,s_img,cv2.TM_CCOEFF_NORMED)
print('result',result)
# 获取坐标
# 获取最大索引
index_max = np.argmax(result)
# 获取到坐标
y,x = np.unravel_index(index_max,result.shape)
print("y:",y,"x:",x)
# 定位到滑块
ele = driver.find_element_by_xpath('/html/body/main/div[1]/div/div[2]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[3]/div/div/div[2]/div/div/div[2]/div[2]')
# 实例化对象
action = ActionChains(driver)
# 拖动滑块
time.sleep(1)
action.drag_and_drop_by_offset(ele,xoffset=x,yoffset=0).perform()
time.sleep(1)
# 定位到验证成功
time.sleep(1)
text = driver.find_element_by_xpath('/html/body/main/div[1]/div/div[2]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[3]/div/div/div[1]/div[2]/span[2]').text
if text == "验证成功":
break
运行代码发现有的时候拖动单次就可以成功,有的则需要拖动多次。这里需要注意的是,本次的拖动是一次性拖动完成的,有的反爬强的网站可能就会出现不成功的问题,后面的文章中会分享一下模拟人拖动轨迹的生成,一定程度上可避免被检测到。