基于opencv的selenium滑動(dòng)驗(yàn)證碼的實(shí)現(xiàn)
基于selenium進(jìn)行動(dòng)作鏈
由于最近很多人聊到滑動(dòng)驗(yàn)證碼怎么處理,所以決定自己動(dòng)手試一下。
做一個(gè)東西前。我們首先要對(duì)這個(gè)東西的操作過(guò)程有一個(gè)大概的了解。
- 打開(kāi)驗(yàn)證碼頁(yè)面。
- 鼠標(biāo)放到拖動(dòng)按鈕上
- 對(duì)拖動(dòng)按鈕進(jìn)行拖動(dòng)
- 拖動(dòng)到陰影快重合的位置。
- 放開(kāi)拖動(dòng)按鈕。
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
artice = browser.find_element_by_class_name('geetest_slider_button') # 滑動(dòng)按鈕
action = ActionChains(browser)
action.click_and_hold(artice).perform() #按住按鈕不放
action.reset_actions()
action.pause(0.01).move_by_offset(step, 0).perform() #step 為滑動(dòng)的水平距離
action.release(artice).perform() # 松開(kāi)按鈕
上面就是本方用到的有關(guān)于ActionChains的方法。其他方法這里不過(guò)多介紹,想了解更多的請(qǐng)轉(zhuǎn)seleniun ActionChains 鼠標(biāo)鍵盤(pán)操作
接下來(lái)到我本次要介紹的重點(diǎn),滑動(dòng)距離的介紹,也就是圖片求陰影區(qū)域的位置。
這里我使用了opencv庫(kù),主要流程包括
- 對(duì)圖像二值化
- 對(duì)二值化的圖像進(jìn)行高斯模糊
- 用canny進(jìn)行邊緣檢測(cè)
- 然后HoughLinesP霍夫變換尋找直線
- 對(duì)符合條件的直線進(jìn)行處理尋找交點(diǎn),進(jìn)而求出我們要找的陰影快的距離
import cv2 as cv
import numpy as np
import math
# 尋找直線
def FindLines(image):
image = cv.cvtColor(image, cv.COLOR_BGR2GRAY) # 二值化
blurred = cv.GaussianBlur(image, (5, 5), 0) # 高斯模糊
canny = cv.Canny(blurred, 200, 400) # canny邊緣檢測(cè)
lines = cv.HoughLinesP(canny, 1, np.pi / 180, 20, minLineLength=15, maxLineGap=8) # 霍夫變換尋找直線
return lines[:, 0, :] # 返回直線
# 這里對(duì)直線進(jìn)行過(guò)濾
def FindResultLises(lines):
resultLines = []
for x1, y1, x2, y2 in lines:
if (abs(y2 - y1) < 5 or abs(x2 - x1) < 5) and min(x1, x2) > 60: # 只要垂直于坐標(biāo)軸的直線并且起始位置在60像素以上
resultLines.append([x1, y1, x2, y2])
return resultLines
# 判斷點(diǎn)是否在直線上
def distAbs(point_exm, list_exm):
x, y = point_exm
x1, y1, x2, y2 = list_exm
dist_1 = math.sqrt(abs((y2 - y1) + (x2 - x1) + 1)) # 直線的長(zhǎng)度
dist_2 = math.sqrt(abs((y1 - y) + (x1 - x) + 1)) + math.sqrt(abs((y2 - y) + (x2 - x) + 1)) # 點(diǎn)到兩直線兩端點(diǎn)距離和
return abs(dist_2 - dist_1)
# 交點(diǎn)函數(shù) y = kx + b 求交點(diǎn)位置
def findPoint(line1, line2):
poit_status = False
x1, y1, x2, y2 = line1
x3, y3, x4, y4 = line2
x = y = 0
if (x2 - x1) == 0: # 垂直x軸
k1 = None
b1 = 0
else:
k1 = 1.0 * (y2 - y1) / (x2 - x1)
b1 = y1 * 1.0 - k1 * x1 * 1.0
if (x4 - x3) == 0:
k2 = None
b2 = 0
else:
k2 = 1.0 * (y4 - y3) / (x4 - x3)
b2 = y3 * 1.0 - k2 * x3 * 1.0
if k1 is None:
if not k2 is None:
x = x1
y = k2 * x1 + b2
poit_status = True
elif k2 is None:
x = x3
y = k1 * x3 + b1
poit_status = True
elif k1 != k2:
x = (b2 - b1) * 1.0 / (k1 - k2)
y = k1 * x * 1.0 + b1 * 1.0
poit_status = True
return poit_status, [x, y]
# 求交點(diǎn)
def linePoint(resultLines):
for x1, y1, x2, y2 in resultLines:
for x3, y3, x4, y4 in resultLines:
point_is_exist, [x, y] = findPoint([x1, y1, x2, y2], [x3, y3, x4, y4]) # 兩線是否有交點(diǎn)
if point_is_exist:
dist_len1 = distAbs([x, y], [x1, y1, x2, y2])
dist_len2 = distAbs([x, y], [x3, y3, x4, y4])
if dist_len1 < 5 and dist_len2 < 5: # 如果誤差在5內(nèi)我們認(rèn)為點(diǎn)在直線上
# 判斷交點(diǎn)在行直線中是左端點(diǎn)還是右端點(diǎn)
if abs(y2 - y1) < 5:
# x1是行直線
if abs(x1 - x) + abs(y1 - y) < 5: # 左端點(diǎn)
return -1, [x, y]
else:
return 1, [x, y]
else:
# x2是行直線
if abs(x3 - x) + abs(y3 - y) < 5:
return -1, [x, y]
else:
return 1, [x, y]
return 0, [0, 0]
if __name__ == '__main__':
img = cv.imread(r'C:\Users\Administrator\Desktop\opencv\temImg.png')
lines = FindLines(img)
lines = FindResultLises(lines)
L_or_R, point_x = linePoint(lines) # L_or_R 用于判斷交點(diǎn)在行直線左邊還是右邊 后面拖動(dòng)要用到
xoffset = point_x[0]
yoffset = point_x[1]
cv.circle(img, (int(xoffset), int(yoffset)), 5, (0, 0, 255), 3)
cv.imshow('circle', img)
cv.waitKey(0)
cv.destroyAllWindows()


效果圖
當(dāng)然也有操作不到的圖片,各位有興趣的可以嘗試并且修改其中的參數(shù)
滑動(dòng)驗(yàn)證碼
在上面我們已經(jīng)找到了邊緣點(diǎn),并且根據(jù)交點(diǎn)是在左邊還是右邊進(jìn)行計(jì)算,找到我們要滑動(dòng)的最后值
if L_or_R == 1: x_offset = xoffset - 20 # 20是陰影快一半的長(zhǎng)度 可根據(jù)實(shí)際情況調(diào)整 else: x_offset = offset + 20
有了滑動(dòng)距離,接下來(lái)就應(yīng)該是滑動(dòng)了
如果我們直接用 action.move_by_offset(x_offset,0).perform() 圖片會(huì)圖示被怪物吃了。那就是運(yùn)動(dòng)軌跡被檢測(cè)到不是正常人的行為,因?yàn)檎H撕茈y一拉就拉到對(duì)應(yīng)的位置。
滑動(dòng)軌跡算法
所以我們還要有一個(gè)模擬人的正常操作的拖動(dòng)軌跡:下面是以先加速再減速的軌跡
import ramdom # 通過(guò)加速減速模擬滑動(dòng)軌跡 def moveTrack(xoffset): updistance = xoffset*4/5 t = 0.2 v = 0 steps_list = [] current_offset = 0 while current_offset<xoffset: if current_offset<updistance: a = 2 + random.random() * 2 else: a = -random.uniform(12,13) vo = v v = vo + a * t x = vo * t + 1 / 2 * a * (t * t) x = round(x, 2) current_offset += abs(x) steps_list.append(abs(x)) # 上面的 sum(steps_list) 會(huì)比實(shí)際的大一點(diǎn),所以再模擬一個(gè)往回拉的動(dòng)作,補(bǔ)平多出來(lái)的距離 disparty = sum(steps_list)-xoffset last1 = round(-random.random() - disparty, 2) last2 = round(-disparty-last1, 2) steps_list.append(last1) steps_list.append(last2) return steps_list
有了軌跡 steps_list 我們就可以通過(guò)循環(huán)來(lái)拖動(dòng)按鈕。需要注意的一點(diǎn)是 每一次循環(huán)都要action.reset_actions() 不然他會(huì)把之前的距離也算進(jìn)來(lái),循環(huán)結(jié)束記得松開(kāi)按鈕
for step in steps_list: action.reset_actions() action.pause(0.01).move_by_offset(step, 0).perform() action.release(artice).perform()
到此這篇關(guān)于基于opencv的selenium滑動(dòng)驗(yàn)證碼的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)opencv selenium滑動(dòng)驗(yàn)證碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python實(shí)現(xiàn)對(duì)照片中的人臉進(jìn)行顏值預(yù)測(cè)
今天給大家?guī)?lái)的是關(guān)于Python實(shí)戰(zhàn)的相關(guān)知識(shí),文章圍繞如何用Python實(shí)現(xiàn)對(duì)照片中的人臉進(jìn)行顏值預(yù)測(cè)展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06
Python中參數(shù)打包和解包的實(shí)現(xiàn)
在Python中,打包和解包參數(shù)是一種操作方式,可以將多個(gè)參數(shù)打包成一個(gè)元組或字典,也可以將一個(gè)元組或字典解包成多個(gè)參數(shù),本文就來(lái)介紹一下如何使用2023-09-09
Python Pillow.Image 圖像保存和參數(shù)選擇方式
今天小編就為大家分享一篇Python Pillow.Image 圖像保存和參數(shù)選擇方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-01-01
Python實(shí)現(xiàn)創(chuàng)建快速剪映草稿軌道自動(dòng)生成視頻
這篇文章主要為大家詳細(xì)介紹了如何使用Python實(shí)現(xiàn)創(chuàng)建快速剪映草稿軌道并自動(dòng)生成視頻,文中的示例代碼講解詳細(xì),需要的可以參考一下2023-08-08
Python流程控制 while循環(huán)實(shí)現(xiàn)解析
這篇文章主要介紹了Python流程控制 while循環(huán)實(shí)現(xiàn)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
python開(kāi)發(fā)實(shí)時(shí)可視化儀表盤(pán)的示例
這篇文章主要介紹了python開(kāi)發(fā)實(shí)時(shí)可視化儀表盤(pán)的示例,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下2021-05-05
Python遠(yuǎn)程方法調(diào)用實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了Python遠(yuǎn)程方法調(diào)用實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
python3用PIL把圖片轉(zhuǎn)換為RGB圖片的實(shí)例
今天小編就為大家分享一篇python3用PIL把圖片轉(zhuǎn)換為RGB圖片的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07

