基于opencv的selenium滑動(dòng)驗(yàn)證碼的實(shí)現(xiàn)
基于selenium進(jìn)行動(dòng)作鏈
由于最近很多人聊到滑動(dòng)驗(yàn)證碼怎么處理,所以決定自己動(dòng)手試一下。
做一個(gè)東西前。我們首先要對(duì)這個(gè)東西的操作過程有一個(gè)大概的了解。
- 打開驗(yàn)證碼頁面。
- 鼠標(biāo)放到拖動(dòng)按鈕上
- 對(duì)拖動(dòng)按鈕進(jìn)行拖動(dòng)
- 拖動(dòng)到陰影快重合的位置。
- 放開拖動(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() # 松開按鈕
上面就是本方用到的有關(guān)于ActionChains的方法。其他方法這里不過多介紹,想了解更多的請(qǐng)轉(zhuǎn)seleniun ActionChains 鼠標(biāo)鍵盤操作
接下來到我本次要介紹的重點(diǎn),滑動(dòng)距離的介紹,也就是圖片求陰影區(qū)域的位置。
這里我使用了opencv庫,主要流程包括
- 對(duì)圖像二值化
- 對(duì)二值化的圖像進(jìn)行高斯模糊
- 用canny進(jìn)行邊緣檢測
- 然后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邊緣檢測 lines = cv.HoughLinesP(canny, 1, np.pi / 180, 20, minLineLength=15, maxLineGap=8) # 霍夫變換尋找直線 return lines[:, 0, :] # 返回直線 # 這里對(duì)直線進(jìn)行過濾 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)) # 直線的長度 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是陰影快一半的長度 可根據(jù)實(shí)際情況調(diào)整 else: x_offset = offset + 20
有了滑動(dòng)距離,接下來就應(yīng)該是滑動(dòng)了
如果我們直接用 action.move_by_offset(x_offset,0).perform()
圖片會(huì)圖示被怪物吃了。那就是運(yùn)動(dòng)軌跡被檢測到不是正常人的行為,因?yàn)檎H撕茈y一拉就拉到對(duì)應(yīng)的位置。
滑動(dòng)軌跡算法
所以我們還要有一個(gè)模擬人的正常操作的拖動(dòng)軌跡:下面是以先加速再減速的軌跡
import ramdom # 通過加速減速模擬滑動(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ǔ)平多出來的距離 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
我們就可以通過循環(huán)來拖動(dòng)按鈕。需要注意的一點(diǎn)是 每一次循環(huán)都要action.reset_actions()
不然他會(huì)把之前的距離也算進(jìn)來,循環(huán)結(jié)束記得松開按鈕
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中的load、loads實(shí)現(xiàn)反序列化的問題
在python自動(dòng)化中,我們傳遞一些參數(shù)是需要從文件中讀取過來的,讀取過來的字典并非python對(duì)象數(shù)據(jù)類型而是string類型。本文給大家分享python中的load、loads實(shí)現(xiàn)反序列化的問題,感興趣的朋友一起看看吧2021-10-10初學(xué)者快看,Python下劃線的五個(gè)作用介紹
大家好,本篇文章主要講的是初學(xué)者快看,Python下劃線的五個(gè)作用介紹,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12Django ORM filter() 的運(yùn)用詳解
這篇文章主要介紹了Django ORM filter() 的運(yùn)用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-05-05python標(biāo)準(zhǔn)庫 datetime的astimezone設(shè)置時(shí)區(qū)遇到的坑及解決
這篇文章主要介紹了python標(biāo)準(zhǔn)庫 datetime的astimezone設(shè)置時(shí)區(qū)遇到的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09Python實(shí)現(xiàn)屬性可修改的裝飾器方式
這篇文章主要介紹了Python實(shí)現(xiàn)屬性可修改的裝飾器方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02Python多進(jìn)程模式實(shí)現(xiàn)多核CPU并行計(jì)算
隨著計(jì)算機(jī)硬件的不斷發(fā)展,多核CPU已經(jīng)成為普及的硬件設(shè)備,在本文中,我們將重點(diǎn)介紹在Python中如何利用多進(jìn)程模式提高程序的執(zhí)行效率,感興趣的可以了解一下2023-05-05對(duì)python中if語句的真假判斷實(shí)例詳解
今天小編就為大家分享一篇對(duì)python中if語句的真假判斷實(shí)例詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-02-02在Django中創(chuàng)建第一個(gè)靜態(tài)視圖
這篇文章主要介紹了在Django中創(chuàng)建第一個(gè)靜態(tài)視圖的方法,與其他編程語言的開始一樣,以Hello world作為示例,需要的朋友可以參考下2015-07-07