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 次循环,即可以成功操做浏览器完成宫格验证码的拖拽填充,松开鼠标以后便可识别成功。 鼠标会慢慢从起始位置移动到终止位置。 最后一个宫格松开以后,验证码的识别便完成了。