【简介】
登陆界面存在验证码是个很头疼的问题,其解决方法为:
1、开发去掉该验证或设置万能码
2、通过tesseract-ocr识别
3、通过第三方验证码接口识别
【实现步骤 】
1、截取登录界面,定位验证码元素,截取验证码部分图片,识别验证码截图获取文本;此处如果验证码截图存在误差,其原因为windows系统下电脑设置的显示缩放比例造成的,location获取的坐标是按显示100%时得到的坐标,而截图所使用的坐标却是需要根据显示缩放比例缩放后对应的图片所确定的,因此就出现了偏差。
解决这个问题有三种方法:
修改电脑显示设置为100%。这是最简单的方法;
缩放截取到的页面图片,即将截图的size缩放为宽和高都除以缩放比例后的大小;
修改Image.crop的参数,将参数元组的四个值都乘以缩放比例。
2、验证码文本获取失败,则重新获取
3、验证码获取成功,则进行登录
以下介绍通过tesseract-ocr识别简单的验证码:
#-*- coding: utf-8 -*-
# python 3.5.0
import re
import requests
import time
from selenium import webdriver
from PIL import Image,ImageEnhance
import pytesseract
fileIndex = 0
def get_auth_code(driver,codeElement):
'''获取验证码'''
global fileIndex
fileName = 'd:/login' + str(fileIndex) + '.png'
#登录界面截图
driver.save_screenshot(fileName)
fileIndex+=1
imgSize = codeElement.size #获取验证码图片的大小
imgLocation = codeElement.location #获取验证码元素坐标
rangle = (int(imgLocation['x']),int(imgLocation['y']),int(imgLocation['x'] + imgSize['width']),int(imgLocation['y']+imgSize['height'])) #计算验证码整体坐标
login = Image.open(fileName)
frame4=login.crop(rangle) #截取验证码图片
realFileName = 'd:/authcode' + str(fileIndex) + '.png'
frame4.save(realFileName)#保存验证码截图
authcodeImg = Image.open(realFileName)
authCodeText = pytesseract.image_to_string(authcodeImg).strip()#识别验证码
return authCodeText#返回验证码文本
def login(driver,authcode):
'''登录系统'''
driver.find_element_by_xpath('//div/ul/li[@class="user"]/input').send_keys("XXXXXXX")
driver.find_element_by_xpath('//div/ul/li[@class="password"]/input').send_keys("123456")
driver.find_element_by_xpath('//div/ul/li[@class="yzm"]/input').send_keys(authcode)
driver.find_element_by_xpath('//div/ul/li[@class="jump"]/button').click()
time.sleep(3)
def isElementExist(element):
flag=True
try:
element=driver.find_element_by_xpath(element)
return flag
except:
flag=False
return flag
def get_yzm(driver):
driver.get('http://XXXXXXXXXXXXXXXXX/login.html')
driver.maximize_window()
time.sleep(5)
imgElement = driver.find_element_by_xpath('//div/ul/li[@class="yzm"]/img')#定位验证码位置
yzm_text=get_auth_code(driver,imgElement)#获取识别的验证码文本
return yzm_text
def login_main(driver):
yzm_text=get_yzm(driver)#获取验证码文本
while len(yzm_text)!=4:#判断验证码是否等于4,不等于重新获取验证码
yzm_text=get_yzm(driver)
login(driver,yzm_text)#验证码识别为4个字符时登录
time.sleep(2)
exit_flag=isElementExist('//div/p[@class="password-tip"]')#如果输入正确的验证码,会弹出div弹框,确认弹框元素是否存在
if exit_flag==True:
login_flag=True
driver.find_element_by_xpath('//div/p/span[@class="edit-off"]').click()#如果div弹框存在,点击取消按钮进入首页
print (login_flag)
else:
login_flag=False
driver.switch_to_alert().accept()#如果输入的验证码不正确,弹出验证码错误alert弹框
return login_flag
def main(driver):
login_flag=None
while login_flag!=True:
login_flag=login_main(driver)
print ("main:"+str(login_flag)
if __name__ == '__main__':
driver = webdriver.Chrome()
main(driver)