记录一次处理极验验证码的心路历程。(主要是看到现有的方法都是通过selenium去模拟拖动)
demo网站:滑动模式
里面有很多不同的极验现有的模式,大家可以参考一下。
本文主要是以最为常用的滑动验证为基础来讲解。
首先分析一下抓包的请求,手动拖动一下滑动验证码,可以看到这个包在提交。
根据返回的内容来看,这个包显然就是我们需要针对的报文。
通过观察参数来看,主要分析的就是参数w,模拟其生成过程。
到这一步,我们可以把整个流程的处理方案分为三步骤,一 针对验证码的图片处理,二得到缺口位置,三生成滑动轨迹,四计算w的参数生成过程。
下面我们来按照这个步骤执行:
寻找图片的url
这分别为background和full的整个图片,但是我们发现其生成的过程是乱序的图片,这该如何处理呢?我们不妨逆向思维一下,我们看到的图层是正常的样子,那么极验肯定是根据一定的规则,将这些图片排列好生成给我们,那么我们只需要找到这个生成的算法即可。
Ge这个函数即为这个图片的生成顺序,所以我们只需要按照这个顺序将图片取出,就可以生成该图片的正常情况。
注意,上图将图片处理的时候还进行了缩放,所以我们生成图片的时候也需要进行缩放处理。
import requests
import PIL.Image as Image
import cv2
class DealImage():
def __init__(self, url, image_save_path):
self.jiyan_sequence = [39, 38, 48, 49, 41, 40, 46, 47, 35, 34, 50, 51, 33, 32, 28, 29, 27, 26, 36, 37, 31, 30, 44, 45,
43, 42, 12, 13, 23, 22, 14, 15, 21, 20, 8, 9, 25, 24, 6, 7, 3, 2, 0, 1, 11, 10, 4, 5, 19, 18, 16, 17]
self.url = url
self.tmp_image_path = './cut/tmp_image.png'
self.image_save_path = image_save_path
def get_image(self):
res = requests.get(self.url).content
with open(self.tmp_image_path, 'wb')as f:
f.write(res)
def cut_image(self):
img = cv2.imread(self.tmp_image_path, cv2.IMREAD_COLOR)
h = img.shape[0]
w = img.shape[1]
# cv2.imshow('test', img)
# cv2.waitKey()
# cv2.destroyAllWindows()
h_size = 80
w_size = 12
h_step = img.shape[0] // h_size
w_step = img.shape[1] // w_size
image_list = []
count = 0
for h in range(h_step):
for w in range(w_step):
img_cut = img[h * h_size:(h + 1) * h_size, w * w_size:(w + 1) * w_size, :]
image_list.append(img_cut[:, :, 1])
cv2.imwrite(('./cut/{}.png'.format(count)), img_cut)
count += 1
def merge_img(self):
image_path = './cut/'
h_size = 80
w_size = 12
# print(file_list)
def image_compose():
to_image = Image.new('RGB', (312, 160))
for i, num in enumerate(self.jiyan_sequence):
height = (i // 26) * h_size
width = ((i - 26) * 12 if i > 25 else i * 12)
# print(width, height, file_list[i])
from_image = Image.open(image_path + '{}.png'.format(num)).resize((w_size, h_size), Image.ANTIALIAS)
to_image.paste(from_image, (width, height))
to_image.resize((260, 160), Image.ANTIALIAS).save(self.image_save_path)
image_compose()
def main(self):
self.get_image()
self.cut_image()
self.merge_img()
print("图片保存完成,保存的路径为:{}".format(self.image_save_path))
if __name__ == '__main__':
# full_img
base_url = 'https://static.geetest.com/'
url = 'pictures/gt/cd0bbb6fe/cd0bbb6fe.jpg'
# bg_img
# url = 'https://static.geetest.com/pictures/gt/7bfaaa72b/bg/5b7598fd8.jpg'
full_image_path = './full.png'
deal_image = DealImage(base_url+url, full_image_path)
deal_image.main()
deal_image = DealImage(base_url+'pictures/gt/cd0bbb6fe/bg/d90272870.jpg', './bg.png')
deal_image.main()
缺口的获取方式其实很简单,将两张图片的像素点值进行色域比较即可,缺口位置的色差肯定大于其他正常位置的缺口,取该值即可。
from PIL import Image
class GetDistance():
def __init__(self, capture1, capture2):
self.capture1 = capture1
self.capture2 = capture2
def get_img(self):
capture1 = Image.open(self.capture1)
capture2 = Image.open(self.capture2)
return capture1, capture2
# 缩放图片
def reszie_img(self, img):
(x, y) = img.size
x_resize = int(x / 2) + 1
y_resize = int(y / 2)
img = img.resize((x_resize, y_resize), Image.ANTIALIAS)
return img
def get_gap_offset(self, img1, img2):
# 起始对比x点
distance = 0
for i in range(distance, img1.size[0]):
for j in range(img1.size[1]):
# 两张图片对比,(i,j)像素点的RGB差距,过大则该x为偏移值
if not self.is_pixel_equal(img1, img2, i, j):
distance = i
return distance
return distance
def is_pixel_equal(self, img1, img2, x, y):
pixel1, pixel2 = img1.load()[x, y], img2.load()[x, y]
sub_index = 100
# 比较RGB各分量的值
if abs(pixel1[0] - pixel2[0]) < sub_index and abs(pixel1[1] - pixel2[1]) < sub_index and abs(
pixel1[2] - pixel2[2]) < sub_index:
return True
else:
return False
def main(self):
capture1, capture2 = self.get_img()
distance = self.get_gap_offset(capture1, capture2)
print(distance)
if __name__ == '__main__':
full_img = './full.png'
bk_img = './bg.png'
get_distance = GetDistance(full_img, bk_img)
get_distance.main()
计算出了距离之后,最主要的就是生成这个滑动轨迹,通过抓包发现其轨迹的逻辑。
但是到目前为止,我也没有找到好的方法可以生成这条轨迹,仍然按照的是远古的方法,根据匀加速和匀减速去生成这个轨迹,目前测试效果并不是很理想,正确率较低。
如果各位看官有什么好的方法 可以高通过率,可以一起探讨。
如涉及版权问题,请联系qq:986361369.(可以商务合作,白嫖党勿扰)
关于w的生成方式,将在下一节中详细介绍。
极验验证码生成(二)_china-mogul-CSDN博客其实关于w的生成方式,我们可以完全可以通过扣代码的方式去实现,不过首先找到w参数的生成js是很重要的。废话不多说,直接上干货。目前我掌握两种方式可以找到w这个参数。1.通过内存漫游的方式(这个后期会进行详细介绍)。2.通过经典的跟栈方式,查找这个函数的生成位置。(主要介绍)滑动一次,我们可以根据chrome寻找到这个ajax的调用栈关系,如下图所示:那么我们可以在这这个js的任意地方下断点,然后重新拖动验证码,让其在你需要的位置段住。这个过程需要很多的耐心,其实我们很https://blog.csdn.net/qq_41733098/article/details/120956006