1、圖形驗證碼的識別php
import tesserocr from PIL import Image image = Image.open('code.jpg') result = tesserocr.image_to_text(image) print(result)
這裏新建了一個 Image 對象,調用 tesserocr 的 image_to_ text()方法。傳入該 Image 對象 便可完成識別。css
tesserocr 還有一個更加簡單的方法,這個方法可直接將圖片文件轉爲字符串,代碼:html
import tesserocr print(tesserocr.file_to_text('image.png'))
此方法的識別效果不如上一種方法好。python
驗證碼處理web
換一個驗證碼帶有多線條,命名爲 code2.jpg。從新識別和實際結果有誤差。算法
對於有線條幹擾狀況,還須要作額外處理,如轉灰度、二值化等操做。 能夠利用 Image 對象的 convert()方法參數傳人 L,便可將圖片轉化爲灰度圖像,示例:json
image = image.convert('L') image.show()
傳入1 便可將圖片進行二值化處理:canvas
image = image.convert('1') image.show()
還能夠指定二值化的閾值,上面的方法採用的是默認閾(yù)值。以上方法採用默認闊值 127。不能直接轉化原圖,要將原圖先轉爲灰度圖像,再指定二值化闊值,代碼:api
import tesserocr from PIL import Image image = Image.open('code.jpg') image = image.convert('L') threshold = 80 table = [] for i in range(256): if i < threshold: table.append(0) else: table.append(1) image = image.point(table,'1') image.show()
變量 threshold 表明二值化閾值,閾值設置爲 80。原來驗證碼中的線條已經去除,整個驗證碼將會變得黑向分明。這時再從新識別驗證碼,代碼:瀏覽器
import tesserocr from PIL import Image image = Image.open('code2.jpg') image = image.convert('L') threshold = 127 table = [] for i in range(256): if i < threshold: table.append(0) else: table.append(1) image = image.point(table,'1') result = tesserocr.image_to_text(image) print(result)
針對一些有干擾的圖片,作一些灰度和二值化處理,會提升圖片識別的正確率。
大概邏輯:
(計次循環首(圖片.取寬度(),x)
計次循環首(圖片.取高度(),y)
‘遍歷每個像素點
‘取出遍歷到的當前像素點顏色
顏色值=到字節集(圖片.取某點顏色值(x-1,y-1))
‘計算灰度值
灰度值=(顏色值[1]+顏色值[2]+顏色值[3])/3
‘將灰度值放回圖片
連續賦值(灰度值,顏色值[1],顏色值[2],顏色值[3])
圖片.寫某點顏色值(x-1,y-1,灰度值)
計次循環尾()
計次循環尾()
圖片.取圖片數據()
2、極驗滑動驗證碼的識別
可使用Selenium來徹底模擬人的行爲的方式來完成驗證。(通常,驗證須要三步:)
能夠同時獲取兩張圖片。設定一個對比閾值,而後遍歷兩張圖片,找出相同位置像素 RGB 差距超過此閾值的像素點,那麼此像素點的位置就是缺口的位置。
from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait EMAIL = 'test@test.com' PASSWORD = '123456' class CrackGeetest(): def __init__(self): self.url = 'https://account.geetest.com/login' self.browser = webdriver.Chrome() self.wait = WebDriverWait(self.browser,20) self.email = EMAIL self.password = PASSWORD
其中, EMAIL 和 PASSWORD 就是登陸極驗須要的用戶名和密碼,若是沒有需先註冊。
模擬點擊
實現第一步的操做,也就是模擬點擊初始的驗證按鈕
定義一個方法來獲取這個按鈕,利用顯式等待的方法來實現,示例:
def get_geetest_button(self): "獲取初始驗證按鈕:return:按鈕對象" button = self.wait.unil(EC.element_to_be_clickable((By.CLASS_NAME,'geetest_radar_tip'))) return button
獲取一個WebElement對象,調用它的click()方法便可模擬點擊,示例:
#點擊驗證按鈕 button = get_geetest_button() button.click()
完成第一步模擬點擊驗證按鈕
識別缺口
識別缺口的位置。
首先獲取先後兩張比對圖片,兩者不一致的地方即爲缺口 。獲取不帶缺口圖片,利用 Selenium選取圖片元素,獲得其所在位置和寬高,而後獲取整個網頁的截圖,圖片裁切出來便可,代碼:
def get_position(self): """獲取驗證碼位置:return:驗證碼位置元組""" img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,'geetest_canvas_img'))) time.sleep(2) location =img.location size = img.size top, bottom, left, right = location['y'],location['y']+size['weight'],location['x'],location['x']+size['width'] return(top, bottom, left, right) def get_geetest_image(self,name='captcha.png'): """獲取驗證碼圖片:return:圖片對象""" top,bottom,left,right = self.get_position() print('驗證碼位置', top, bottom, left, right) screenshot = self.get_screenshot() captcha = screenshot.crop((left, top, right, bottom)) return captcha
這裏 get_position()函數首先獲取圖片對象,獲取它的位置和寬高,隨後返回其左上角和右下角的座標 get_geetest_image()方法獲取網頁截圖,調用 crop()方法將圖片裁切出來,返回的是 Image 對象
def get_slider(self): """獲取滑塊:return:滑塊對象""" slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME,'greetest_slider_button'))) return slider
利用 get_slider()方法獲取滑塊對象,調用 click()方法便可觸發點擊,缺口圖片便可呈現,代碼:
#點按呼出缺口 slider = self.get_slider() slider.click()
調用 get_geetest_image()方法將第二張圖片獲取下來便可。
def is_pixel_equal(self, image1, image2, x, y): """判斷兩個像素是否相同 :param image1:圖片1 :param image1:圖片1 :param x:位置x :param y:位置y :return:像素是否相同""" #取兩個圖片的像素點 pixel1 = image1.load()[x, y] pixel2 = image2.load()[x, y] threshold = 60 if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs(pixel1[2] -pixel2[2])<threshold: return True else: return False def get_gap(self, image1, image2): """獲取缺口偏移量 :param image1:不帶缺口圖片 :param image2:帶缺口圖片 :return:""" left = 60 for i in range(left,image1.size[0]): for j in range(image1.size[1]): if not self.is_pixel_equal(image1, image2, i, j): left = i return left return left
get_gap()方法即獲取缺口位置的方法。此方法的參數是兩張圖片, 一張爲帶缺口圖片,另外一張爲不帶缺口圖片。遍歷兩張圖片的每一個像素,利用 is_pixel_equal()方法判斷兩張圖片同一位置的 像素是杏相同。比較兩張圖 RGB 的絕對值是否均小於定義的閾值 threshold。若是絕對值均在闊值之 內,則表明像素點相同,繼續遍歷。不然表明不相同的像素點,即缺口的位置。
def get_track(self, distance): """根據偏移量獲取移動軌跡 :param distance:偏移量 :return: 移動軌跡""" #移動軌跡 track = [] #當前位移 current = 0 #減速閾值 mid = distance * 4 / 5 #計算間隔 t = 0.2 #初速度 v = 0 while current < distance: if current < mid: a = 2 else: a = -3 #初速度 V0 v0 = v v = v0 + a*t move = v0 *t +1/2 *a *t *t current += move #加入軌跡 track.append(round(move)) return track
定義 get_ rack()方法,傳人的參數爲移動的總距離,返回的是運動軌跡。運動軌跡用 track 表示,是一個列表,列表的每一個元素表明每次移動多少距離。
定義變量 mid,即減速的闊值,也就是加速到什麼位置開始減速。這裏 mid 值爲 4/5,即模擬前 4/5 路程是加速過程,後 1/5 路程是減速過程。
def move_to_gap(self, slider,tracks): """拖動滑塊到缺口處 :params slider:滑塊 :params tracks:軌跡 :return:""" ActionChains(self,browser).click_and_hold(slider).perform() for x in tracks: ActionChains(self,browser).move_by_offset(xoffset=x,yoffset=0).perform() time.sleep(0.5) ActionChains(self.browser).release().perform()
傳人的參數爲滑塊對象和運動軌跡。首先調用 ActionChains 的 click_and_ hold()方法按住拖動底部滑塊,遍歷運動軌跡獲取每小段位移距離,調用 move_by_offset()方法移動此位移,最後調用 release()方法鬆開鼠標便可。
完整代碼(需適當修改參數):
import time from io import BytesIO from PIL import Image from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC EMAIL = 'cqc@cuiqingcai.com' PASSWORD = '' BORDER = 6 INIT_LEFT = 60 class CrackGeetest(): def __init__(self): self.url = 'https://account.geetest.com/login' self.browser = webdriver.Chrome() self.wait = WebDriverWait(self.browser, 20) self.email = EMAIL self.password = PASSWORD def __del__(self): self.browser.close() def get_geetest_button(self): """ 獲取初始驗證按鈕 :return: """ button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_radar_tip'))) return button def get_position(self): """ 獲取驗證碼位置 :return: 驗證碼位置元組 """ img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_img'))) time.sleep(2) location = img.location size = img.size top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size[ 'width'] return (top, bottom, left, right) def get_screenshot(self): """ 獲取網頁截圖 :return: 截圖對象 """ screenshot = self.browser.get_screenshot_as_png() screenshot = Image.open(BytesIO(screenshot)) return screenshot def get_slider(self): """ 獲取滑塊 :return: 滑塊對象 """ slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_slider_button'))) return slider def get_geetest_image(self, name='captcha.png'): """ 獲取驗證碼圖片 :return: 圖片對象 """ top, bottom, left, right = self.get_position() print('驗證碼位置', top, bottom, left, right) screenshot = self.get_screenshot() captcha = screenshot.crop((left, top, right, bottom)) captcha.save(name) return captcha def open(self): """ 打開網頁輸入用戶名密碼 :return: None """ self.browser.get(self.url) email = self.wait.until(EC.presence_of_element_located((By.ID, 'email'))) password = self.wait.until(EC.presence_of_element_located((By.ID, 'password'))) email.send_keys(self.email) password.send_keys(self.password) def get_gap(self, image1, image2): """ 獲取缺口偏移量 :param image1: 不帶缺口圖片 :param image2: 帶缺口圖片 :return: """ left = 60 for i in range(left, image1.size[0]): for j in range(image1.size[1]): if not self.is_pixel_equal(image1, image2, i, j): left = i return left return left def is_pixel_equal(self, image1, image2, x, y): """ 判斷兩個像素是否相同 :param image1: 圖片1 :param image2: 圖片2 :param x: 位置x :param y: 位置y :return: 像素是否相同 """ # 取兩個圖片的像素點 pixel1 = image1.load()[x, y] pixel2 = image2.load()[x, y] threshold = 60 if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs( pixel1[2] - pixel2[2]) < threshold: return True else: return False def get_track(self, distance): """ 根據偏移量獲取移動軌跡 :param distance: 偏移量 :return: 移動軌跡 """ # 移動軌跡 track = [] # 當前位移 current = 0 # 減速閾值 mid = distance * 4 / 5 # 計算間隔 t = 0.2 # 初速度 v = 0 while current < distance: if current < mid: # 加速度爲正2 a = 2 else: # 加速度爲負3 a = -3 # 初速度v0 v0 = v # 當前速度v = v0 + at v = v0 + a * t # 移動距離x = v0t + 1/2 * a * t^2 move = v0 * t + 1 / 2 * a * t * t # 當前位移 current += move # 加入軌跡 track.append(round(move)) return track def move_to_gap(self, slider, track): """ 拖動滑塊到缺口處 :param slider: 滑塊 :param track: 軌跡 :return: """ ActionChains(self.browser).click_and_hold(slider).perform() for x in track: ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform() time.sleep(0.5) ActionChains(self.browser).release().perform() def login(self): """ 登陸 :return: None """ submit = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'login-btn'))) submit.click() time.sleep(10) print('登陸成功') def crack(self): # 輸入用戶名密碼 self.open() # 點擊驗證按鈕 button = self.get_geetest_button() button.click() # 獲取驗證碼圖片 image1 = self.get_geetest_image('captcha1.png') # 點按呼出缺口 slider = self.get_slider() slider.click() # 獲取帶缺口的驗證碼圖片 image2 = self.get_geetest_image('captcha2.png') # 獲取缺口位置 gap = self.get_gap(image1, image2) print('缺口位置', gap) # 減去缺口位移 gap -= BORDER # 獲取移動軌跡 track = self.get_track(gap) print('滑動軌跡', track) # 拖動滑塊 self.move_to_gap(slider, track) success = self.wait.until( EC.text_to_be_present_in_element((By.CLASS_NAME, 'geetest_success_radar_tip_content'), '驗證成功')) print(success) # 失敗後重試 if not success: self.crack() else: self.login() if __name__ == '__main__': crack = CrackGeetest() crack.crack()
3、點觸驗證碼的識別
import requests from hashlib import md5 class Chaojiying(object): def __init__(self, username, password, soft_id): self.username = username self.password = md5(password.encode('utf-8')).hexdigest() self.soft_id = soft_id self.base_params = { 'user':self.username, 'pass2':self.password, 'softid':self.soft_id, } self.headers = { 'Connection':'Keep_Alive', 'User-Agent':'Mozilla/4.0(compatible;MSIE 8.0; Windows NT 5.1; Trident/4.0)', } def post_pic(self, im, codetype): """ im: 圖片字節 codetype: 題目類型參考 http://www.chaojiying.com/price.html """ params = { 'codetype':codetype, } params.update(self.base_params) files = {'userfile':('ccc.jpg',im)} r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers) return r.json() def report_error(self,im_id): """ im_id:報錯題目的圖片ID """ params = { 'id':im_id, } params.update(self.base_params) r = requests.post('http://Upload.chaojiying.net/Upload/ReportError.php',data=params, headers= self.headers) return r.json()
這裏定義一個chaojiying類,構造函數接收三個參數,分別是超級鷹用戶名、密碼以及軟件ID,保存以備使用。最重要的一個方法:post_pic(),須要傳入圖片對象和驗證碼的代號,該方法會將圖片對象和相關信息發給超級鷹後臺進行識別,而後將識別成功的JSON返回
EMAIL = 'Mack01' PASSWORD = '超級鷹密碼' #超級鷹用戶名、密碼、軟件ID、驗證碼類型 CHAOJIYING_USERNAME = 'Germey' CHAOJIYING_PASSWORD = '' CHAOJIYING_SOFT_ID = 893590 CHAOJIYING_KIND = 9102 class CrackTouClick(): def __init__(self): self.url = 'http://admin.touclick.com/login.html' self.browser = webdriver.Chrome() self.wait = WebDriverWait(self.browser,20) self.email = EMAIL self.password =PASSWORD self.chaojiying = Chaojiying(CHAOJIYING_USERNAME, CHAOJIYING_PASSWORD, CHAOJIYING_SOFT_ID)
獲取驗證碼
完善表單,模擬點擊呼出驗證碼,代碼:
def open(self): """ 打開網頁輸入用戶名密碼 return: None """ self.browser.get(self.url) email =self.wait.until(EC.present_of_element_located((By.ID,'email'))) password = self.wait.until(EC.present_of_element_located((By.ID,'password'))) email.send_keys(self.email) password.send_keys(self.password) def get_touclick_button(self): """ 獲取初始驗證按鈕 return: """ button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME,'touclick-hod-wrap'))) return button
open()方法負責填寫表單,get_touclick_button()方法獲取驗證碼按鈕,以後觸發點擊便可。
接下來,相似極驗驗證碼圖像獲取同樣,獲取驗證碼圖片的位置和大小,從網頁截圖裏截取相應 的驗證碼圖片,代碼實現以下所示:
def get_touclick_element(self): """ 獲取驗證圖片對象 return: 圖片對象 """ element = self.wait.until(EC.present_of_element_located((By.CLASS_NAME,'touclick-pub-content'))) return element def get_position(self): """ 獲取驗證碼位置 return: 驗證碼位置元組 """ element =self.get_touclick_element() time.sleep(2) location = element.location size = element.size top, bottom, left, right = location['y'],location['y']+size['height'],location['x'],location['x']+size['width'] return (top, bottom, left, right) def get_screenshot(self): """ 獲取網頁截圖 return: 截圖對象 """ screenshot = self.browser.get_screenshot_as_png() screenshot = Image.open(BytesIO(screenshot)) return screenshot def get_touclick_image(self, name='captcha.png'): """ 獲取驗證碼圖片 return: 圖片對象 """ top,bottom,left,right =self.get_position() print('驗證碼位置',top,bottom, left ,right) screenshot = self.get_screenshot() captcha = screenshot.crop((left,top,right,bottom)) return captcha
get_ touclick_image()方法即爲從網頁截圖中截取對應的驗證碼圖片,其中驗證碼圖片的相對位 置座標由 get position()方法返回獲得。 最後咱們獲得的是 Image 對象
識別驗證碼
調用 Chaojiying 對象的 post_pic()方法,便可把圖片發送給超級鷹後臺,這裏發送的圖像是字節 流格式,代碼實現以下所示:
image = self.get_touclick_image() bytes_array = BytesIO() image.save(bytes_array, format='PNG') #識別驗證碼 result = self.chaojiying.post_pic(bytes_array.getvalue(),CHAOJIYING_KIND) print(result)
運行以後, result 變量就是超級鷹後臺的識別結果。 運行須要等待幾秒。
返回的結果是一個 JSON。 若是識別成功,典型的返回結果以下所示 :
{’ err_no’:0, 'err_str’: 'OK', 'pic_id’: ’6002001380949200001', 'pic_str' :'132,127|56, 77 ','md5': '1f8e1d4bef8b11484cb1f1f34299865b'}
其中,pic_str 就是識別的文字的座標,是以字符串形式返回的,每一個座標都以|分隔。接下來只須要將其解析,而後模擬點擊,代碼:
def get_points(self, captcha_result): """ 解析識別結果 param captcha_result: 識別結果 return: 轉化後的結果 """ groups = captcha_result.get('pic_str').split('|') locations = [[int(number) for number in group.split(',')] for group in groups] return locations def touch_click_words(self,locations): """ 點擊驗證圖片 param locations:點擊位置 return: None """ for location in locations: print(location) ActionChains(self.browser).move_to_element_with_offset(self.get_touclick_element(),location[0],location[1]).click().perform() time.sleep(1)
這裏用 get_points()方法將識別結果變成列表的形式。touch_click_words()方法則經過調用 move_to_element_with_offset()方法依次傳入解析後的座標,點擊便可。
這樣就模擬完成座標的點選,最後點擊提交驗證的按鈕, 等待驗證經過,再點擊登陸按鈕便可成功登陸。
4、微博宮格驗證碼的識別
通常選用全圖匹配的方式來進行識別。找到匹配的模板以後,就能夠獲得事先爲模板定義的拖動順序,而後模擬拖動便可。
import time from io import BytesIO from PIL import Image from selenium import webdriver from selenium.common.exceptions import TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC USERNAME = '' PASSWORD = '' class CrackWeiboSlide(): def __init__(self): self.url = 'https://passport.weibo.cn/signin/login' self.browser = webdriver.Chrome() self.wait = WebDriverWait(self.browser,20) self.username = USERNAME self.password = PASSWORD def __del__(self): self.browser.close() def open(self): """ 打開網頁輸入用戶名密碼並點擊 return: None """ self.browser.get(self.url) username = self.wait.until(EC.presence_of_element_located((By.ID,'loginName'))) password = self.wait.until(EC.presence_of_element_located((By.ID,'loginPassword'))) submit = self.wait.until(EC.element_to_be_clickable((By.ID,'loginAction'))) username.send_keys(self.username) password.send_keys(self.password) submit.click() def get_position(self): """ 獲取驗證碼位置 return: 驗證碼位置元組 """ global img try: img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,'Patt-shadow'))) except TimeoutException: print('未出現驗證碼') self.open() time.sleep(2) location = img.location size = img.size top,bottom, left, right = location['y'],location['y']+size['height'],location['x'],location['x']+size['width'] return (top, bottom, left, right) def get_screenshot(self): """ 獲取網頁截圖 return: 截圖對象 """ screenshot = self.browser.get_screenshot_as_png() screenshot = Image.open(BytesIO(screenshot)) return screenshot def get_image(self, name='captcha.png'): """ 獲取驗證碼嗎圖片 return: 圖片對象 """ top, bottom, left, right = self.get_position() print('驗證碼位置', top, bottom,left, right) screenshot = self.get_screenshot() captcha = screenshot.crop((left, top, right, bottom)) captcha.save(name) return captcha def main(self): """ 批量獲取驗證碼 return: 圖片對象 """ count = 0 while True: self.open() self.get_image(str(count)+'.png') count +=1 if __name__ =='__main__': crack = CrackWeiboSlide() crack.main()
只須要挑選出不一樣的 24 張驗證碼圖片並命名保存。 名稱能夠直接取做宮格的滑動的順序,識別過程只須要遍歷模板進行匹配。
調用 get_image()方法,獲得驗證碼圖片對象。而後,對驗證碼圖片對象進行模板匹配,定義以下方法:
from os import listdir def detect_image(self,image): """ 匹配圖片 param image: 圖片 return: 拖動順序 """ for template_name in listdir(TEMPLATES_FOLDER): print('正在匹配', template_name) template = Image.open(TEMPLATES_FOLDER + template_name) if self.same_image(image, template): #返回順序 numbers = [int(number) for number in list(template_name.split('.')[0])] print('拖動順序',numbers) return numbers
TEMPLATES_FOLDER 就是模板所在的文件夾。 經過 listdir()方法獲取全部模板的文件名稱,而後對其進行遍歷,經過 same_image()方法對驗證碼和模板進行比對。 若是匹配成功,就將匹配到的模板文件名轉換爲列表。例:模板文件 3124.png匹配到,返回結果爲[3,1,2,4].
對比的方法實現以下:
def is_pixel_equal(self, image1, image2, x, y): """ 判斷兩個像素是否相同 :param image1: 圖片1 :param image2: 圖片2 :param x: 位置x :param y: 位置y :return: 像素是否相同 """ # 獲取兩個圖片的像素點 pixel1 = image1.load()[x, y] pixel2 = image2.load()[x, y] threshold = 20 if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs( pixel1[2] - pixel2[2]) < threshold: return True else: return False def same_image(self, image, template): """ 識別類似驗證碼 param image: 待識別驗證碼 param template: 模板 return: """ # 相識度閾值 threshold = 0.99 count = 0 for x in range(image.width): for y in range(image.height): # 判斷像素是否相同 if self.is_pixel_equal(image, template, x, y): count += 1 result = float(count) / (image.width * image.height) if result > threshold: print('功能匹配') return True return False
在這裏比對圖片也利用了遍歷像素的方法。 same_image()方法接收兩個參數,image 爲待檢測的驗證碼圖片對象,template 是模板對象。因爲兩者大小是徹底一致的,因此在這裏遍歷了圖片的全部像素點。比對兩者同一位置的像素點,若是像素點相同,計數就加 1。最後計算相同的像素點佔總像素的比例。若是該比例超過必定閾值,那就斷定圖片徹底相同,則匹配成功。這裏闊值設定爲 0.99, 即若是兩者有 0.99 以上的類似比,則表明匹配成功。 依次匹配 24 個模板。 若是驗證碼圖片正常,咱們總能找到一個匹配的模板, 這樣就能夠獲得宮格的滑動順序了。
模擬拖動
根據滑動順序拖動鼠標,鏈接各個宮格,方法實現以下所示:
def move(self, numbers): """ 根據順序拖動 """ #得到四個按點 circles = self.browser.find_elements_by_css_selector('.patt-wrap. patt-circ') dx = dy =0 for index in range(4): circle = circles[numbers[index]-1] #若是是第一次循環 if index == 0: # 點擊第一個按點 ActionChains(self.browser)\.move_to_element_with_offset(circle, circle.size['width']/2, circle.size['height']/2 )\.click_and_hold().perform() else: #小幅移動次數 times = 30 #拖動 for i in range(times): ActionChains(self.browser).move_by_offset(dx/times, dy/times).perform() time.sleep(1/times) # 若是是最後一次循環 if index == 3: #鬆開鼠標 ActionChains(slef.browser).release().perform() else: #計算下一次偏移 dx = circles[numbers[index +1]-1].location['x'] - circle.location['x'] dy = circles[numbers[index +1]-1].location['y'] - circle.location['y']
這裏方法接收的參數就是宮格的點按順序,如 [3,1,2,4]。首先利用 find_elements_by_css_selector()方法獲取到 4 個宮格元素,它是一個列表形式,每一個元素表明一個宮格。接下來遍歷宮格的點按順序,作一系列對應操做。
其中若是當前遍歷的是第一個宮格,那就直接鼠標點擊並保持動做,不然移動到下一個宮格。若是當前遍歷的是最後一個宮格,那就鬆開鼠標,若是不是最後一個宮格,則計算移動到下一個宮格的偏移盤。
經過 4 次循環,即可以成功操做瀏覽器完成宮格驗證碼的拖拽填充,鬆開鼠標以後便可識別成功。 鼠標會慢慢從起始位置移動到終止位置。 最後一個宮格鬆開以後,驗證碼的識別便完成了。