介绍:

验证码种类:纯数字、纯字母、汉字组合、数学运算题、滑动坐标、图片、短信、邮箱、语音等等。

验证码作用:验证码作用能有效防止恶意登录注册,基于网址性能减少用户的并发。

实现原理:验证码于服务器端生成,发送给客户端,并以图像格式显示(对图像加以处理:添加干扰项、添加干扰像素、添加噪点等)。客户端提交所显示的验证码,客户端接收并进行比较,若比对失败则不能实现登录或注册,反之成功后跳转相应界面。


自动化中解决验证码的解决方案

类别

描述

优点

选哟考虑


  • 去掉验证码

把验证码的相关代码注释掉

省去麻烦

存在风险

安全问题


  • 设置万能码

设置一个“万能验证码”




  • 保留一个资源

在指定的文件夹资源库中进行随机一张图片




  • 光学字符识别

Tesseract OCR 引擎的 Python 封装类

能读取常规的图片文件(JPG, GIF ,PNG , TIFF 等)。



  • 打码平台识别

主流打码平台:斐斐、超人、图鉴等




  • 记录cookie

在浏览器中添加登录成功时所携带的cookie来跳过登录,

selenium中可以通过add_cookie()方法将用户名、密码的登录信息写入浏览器的cookie中



(一)光学字符识别

1.安装第三方模块pytessract和图像处理库

pip install pytesseract
pip  install Pillow

注意:python2.X版本安装库PIL,但是在python3.X版本须安装Pillow或Pillow-PIL2

2.安装ocr识别库tesseract:

下载地址:https://github.com/UB-Mannheim/tesseract/wiki

安装办法:https://www.cnblogs.com/sea-stream/p/10961580.html

3.简单识别

  • 一般思路:图片降噪——》 图片切割——》 图像文本输出
  • 图片降噪:是把不需要的信息通通去除,比如背景,干扰线,干扰像素等等,只剩下需要识别的文字,让图片变成2进制点阵最好。

a 彩色背景的验证码:

每个像素都可以放在一个5维的空间里,这5个维度分别是,X,Y,R,G,B,也就是像素的坐标和颜色。处理以下验证码图片:

python自动化测试Selenium:7  Web自动化验证码处理_验证码

b 彩色图像转化为灰度

RBG转化到HSI彩色空间,采用L分量:

from PIL import Image
image = Image.open('3.jpg')
img_new = image.convert('L')
img_new.show()

python自动化测试Selenium:7  Web自动化验证码处理_html_02

c 二值化处理:

二值化是图像分割的一种常用方法。在二值化图象的时候把大于某个临界灰度值的像素灰度设为灰度极大值,把小于这个值的像素灰度设为灰度极小值,从而实现二值化(一般设置为0-1)。根据阈值选取的不同,二值化的算法分为固定阈值和自适应阈值,这里选用比较简单的固定阈值。

from pytesseract import pytesseract
from PIL import Image
image = Image.open("3.jpg")
get_new_image=image.convert("L")
im_new = get_new_image.point(lambda x: 0 if x<143 else 255) #二值化处理
#im_new.show()
get_result=pytesseract.image_to_string(im_new)
print(get_result)

得到结果如下:

python自动化测试Selenium:7  Web自动化验证码处理_Image_03


d 转成黑白图片-解决识别率低

from PIL import ImageEnhance
enhancer = ImageEnhance.Contrast(im_new)
image2 = enhancer.enhance(4)
get_result=pytesseract.image_to_string(image2)
print(get_result)

得到结果如下:

python自动化测试Selenium:7  Web自动化验证码处理_验证码_04


(二)基于cookie登录操作

  获取cookie通常有两种方式,一是使用驱动器对象中的get_cookies方法获取当前项目中的cookie,二是通过抓包工具抓取出对应的cookis,然后再将cookis添加在数据中。

#获取cookies并保存到cookie.txt
from selenium import webdriver
import json

# 下面是chromedriver路径,自己填
browser = webdriver.Chrome()
# 打开要自动登录的网站,比如说csdn
browser.get("http://192.168.141.100/index.php/Admin/login/index.html")
# 手动完成登录后,随便在控制台输入内容,就保存下来了
input("等待登录成功,登录成功后随便输入内容。")
dictCookies = browser.get_cookies()
jsonCookies = json.dumps(dictCookies)

with open('cookies.txt', 'w') as f:
    f.write(jsonCookies)
print('cookies保存成功!')
#通过cookie.txt文件中内容进行登录
from selenium import webdriver
import json

# 下面是chromedriver路径,自己填
browser = webdriver.Chrome()
# 打开要自动登录的网站
browser.get("http://192.168.141.100/index.php/Admin/login/index.html")
with open('cookies.txt', 'r', encoding='utf8') as f:
    listCookies = json.loads(f.read())
for cookie in listCookies:
    cookie_dict = {  # domain看cookies第一个字段
        'domain': '192.168.141.100',
        'name': cookie.get('name'),
        'value': cookie.get('value'),
        "expires": '',
        'path': '/',
        'httpOnly': False,
        'HostOnly': False,
        'Secure': False}
    browser.add_cookie(cookie_dict)
    browser.refresh()  # 刷新网页,cookies才成功
browser.get("http://192.168.141.100/index.php/Admin/login/index.html")

(三)x打码平台识别

     下面以登陆DS_MALL商城后台为例:

python自动化测试Selenium:7  Web自动化验证码处理_验证码_05

使用电脑自带的画图工具,获取截图中的验证码图片X、Y轴坐标

python自动化测试Selenium:7  Web自动化验证码处理_Image_06

首先需要截取到验证码图片,截取代码:

# 获取页面中的验证码图片

import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from PIL import Image


class GetCodeImage(object):
    def __init__(self):
        url = 'http://192.168.141.100/index.php/Admin/login/index.html'
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.get(url)
        self.driver.implicitly_wait(10)

    def get_code_image(self):
        self.driver.get_screenshot_as_file('index.png')
        # 需要获取验证码的位置
        code_element = self.driver.find_element(By.ID, 'change_captcha')

        # 这里输出定位到的x,y坐标,根据画图工具查看的坐标,进行相加或者相减,这个数值不是固定的,每个人的电脑型号不同分辨率不同,坐标不同
        loct = self.driver.find_element(By.ID, 'change_captcha').location
        print(loct)
        # 输出{'x': 900, 'y': 372},画图工具显示的坐标是{'x': 1350, 'y': 558},补上相差的数据450,186

        # 获取验证码图片在截图中的坐标位置和大小
        left = code_element.location['x']+450
        upper = code_element.location['y']+186
        right = code_element.size['width']+52 + left
        bottom = code_element.size['height']+12 + upper

        # 创建image对象,打开之前的截图
        image = Image.open('index.png')
        # 根据坐标点截取图片,另存为
        code_image = image.crop((left, upper, right, bottom))
        code_image.save('code.png')
        print("Success")
        self.driver.quit()



if __name__ == '__main__':
    get_code_png = GetCodeImage()
    get_code_png.get_code_image()

然后通过打码平台(http://ttshitu.com/docs/python.html#pageTitle)完成验证码的读取,每个打码平台都有对应的开发文档,根据所提供的开发APi进行调用接口;

例如:

python自动化测试Selenium:7  Web自动化验证码处理_验证码_07

在pycharm中新建一个模块TuJian_APi

#FileName:          CloudCode.py

import json
import requests
import base64
from io import BytesIO
from PIL import Image
from sys import version_info

def base64_api(uname, pwd,  img):
    img = img.convert('RGB')
    buffered = BytesIO()
    img.save(buffered, format="JPEG")
    if version_info.major >= 3:
        b64 = str(base64.b64encode(buffered.getvalue()), encoding='utf-8')
    else:
        b64 = str(base64.b64encode(buffered.getvalue()))
    data = {"username": uname, "password": pwd, "image": b64}
    result = json.loads(requests.post("http://api.ttshitu.com/base64", jsnotallow=data).text)
    if result['success']:
        return result["data"]["result"]
    else:
        return result["message"]
    return ""

if __name__ == "__main__":
    img_path = "code.png"
    img = Image.open(img_path)
    result = base64_api(uname='wood', pwd='wood1314', img=img)
    print(result)

最后调用该模块即可:

综合代码如下:

#FileName:          DSMall_Login.py


#完成dsmall登陆成功操作
from Day18.BaseModule.Base_Class import BaseClass
from Day21.Check_Code.CloudCode import base64_api
#PIL包中的image模块
from PIL import Image
import time
class Dsmall_Login(BaseClass):
    def __init__(self,url,browserType):
        super().__init__(url,browserType)


    #获取验证码图片:然后再把验证码图片发送给第三方服务器
    def  get_code_image(self):
        #获取整个页面的图片
        self.get_driver.get_screenshot_as_file("index.png")
        #需要获取验证码的位置
        #get_code_element=self.get_driver.find_element_by_id("codeimage")
        get_code_element = self.get_driver.find_element_by_id("change_captcha")
        get_left=get_code_element.location["x"]
        get_upper=get_code_element.location["y"]
        get_right=get_code_element.size["width"]+get_left
        get_lower=get_code_element.size["height"]+get_upper
        #创建image对象
        get_image=Image.open("index.png")
        #根据验证码的坐标点进行截取
        get_new_image=get_image.crop((get_left,get_upper,get_right,get_lower))
        get_new_image.save("code.png")


    #完成验证码的输入操作:把验证码发送给第三方服务器
    def get_code(self,uname,pwd,img):
        get_code=base64_api(uname,pwd,img)
        print(get_code)
        self.get_driver.find_element_by_name("captcha").send_keys(get_code)
        #self.get_driver.find_element_by_id("captcha_normal").send_keys(get_code)




if __name__ == '__main__':
    #ds=Dsmall_Login("http://123.57.71.195:8787/index.php/home/Login/login.html?ref_url=%2Findex.php%2Fhome%2Fmember%2Findex.html","Chrome")
    ds = Dsmall_Login("http://123.57.71.195:8787/index.php/Admin/login/index.html","Chrome")
    ds.get_code_image()
    ds.get_code(uname='wood', pwd='wood1314', img=Image.open("code.png"))