首先,我们来理一下思路:
极验是专业提供第三方服务的,既然是第三方服务,就表明 验证滑动是否成功的服务端是在极验的后台。
那么用户的流程就应该是:
1、访问目标网页,获得表明商户的参数
↓
2、带着这个参数请求极验,获得滑动图片
↓
3、用户拖动图片,返回轨迹等数据给极验
↓
4、极验返回验证结果,如果成功则附带一个验证成功的参数
↓
5、携带这个参数即可请求目标网页后续内容
那其实我们就可以利用这个三方交互的流程,尽量让我们的代码可复用。
所以思路很清晰,我们的流程就应该是:
1、访问目标网页,获得表明商户的参数
↓
2、调用我们的服务,获得一个验证成功的参数
↓
3、携带这个参数即可请求目标网页后续内容
也就是说,我们的代码是只与极验交互,传入一个参数,返回一个参数即可。
我们先来看一下极验的请求参数:
很明显,两个参数,gt 和 challenge 。
极验的官方使用文档里面有说明:
果然,就跟我们的推测一样,我们只需要请求目标网页即可拿到这两个参数。
而最终的验证成功返回值:
这个validate就是我们需要的参数。
也就是:
gt, challenge = get_gt() #和目标网站交互
validate = get_validate(gt, challenge) #和极验交互
result = get_result(validate) #和目标网站交互
很明显,我们可以复用的就是 get_validate,这也是破解的重点:
那首先我们需要一个滑动验证码的模板:
极验文档中直接有使用样例:https://www.geetest.com/demo/slide-custom.html
但是他的传入参数已经写死,所以我们需要对这个html进行加工一下:
可以看到他取参数是直接调用ajax,参数放在data中:
而我们的需求是参数可以变化的,所以我们只需要稍作修改:
请求时只需用get请求传入参数即可。
接下来就是常规的selenium模拟滑动的内容了,网上样例很多,我就不多说了。
只需要注意一点就是url需要使用我们自己的html:
url = './jiyan.html?success=1&new_captcha=true>={}&challenge={}'.format(gt, challenge)
补充一点:
极验的图片是使用convas直接生成的,拼接比较繁琐,我们使用selenium直接截图比较方便:
其中image1, image2分别为滑块在最左端和最右端时的截图,主要是用来确定y的位置,裁剪图片,提高准确率。
二值化阈值通过y的位置范围内的平均阈值来确定。
# 通过比较两张图片确定y位置
def get_y(image1, image2):
y_s = []
for i in range(image1.size[0] - 60, image1.size[0]):
for j in range(image1.size[1]):
rgb1 = image1.load()[i, j]
rgb2 = image2.load()[i, j]
if rgb1[1] == rgb2[1] and rgb1[2] == rgb2[2] and rgb1[3] == rgb2[3]:
continue
y_s.append(j)
y_s_s = []
for y in range(min(y_s), max(y_s)):
if y_s.count(y) > 40:
y_s_s.append(y)
return max(y_s_s), min(y_s_s)
# 获取图片的平均灰度值
def get_ave_rgb(image1):
rgb = []
for i in range(image1.size[0]):
for j in range(image1.size[1]):
rgb.append(image1.load()[i, j])
return np.mean(rgb)
def get_x(img_11, img_22):
y1, y2 = get_y(img_11, img_22)
cropImg = img_11.crop((0, y2, img_11.size[0], y1))
image1 = cropImg.convert('L')
threshold = int(get_ave_rgb(image1)) - 30 # 阈值通过平均灰度值确定
# 二值化
table = []
for i in range(256):
if i < threshold:
table.append(0)
else:
table.append(1)
img = image1.point(table, '1')
img.save('tu3.png')
node_list = []
for x in range(40, img.size[0] - 80, 2):
# (x0,y0,x1,y1)
box1 = (x, 0, x + 43, img.size[1])
image1 = img.crop(box1)
# image1.show()
matrix = np.asarray(image1)
node_num = np.sum(matrix)
node_list.append((x, node_num))
return min(node_list, key=lambda x: x[1])