首先,我們來理一下思路:
極驗是專業提供第三方服務的,既然是第三方服務,就表明 驗證滑動是否成功的服務端是在極驗的後臺。
那麼用戶的流程就應該是:
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])