自动化测试如何避开图片验证码?

发表于:2022-6-20 09:23

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:我很方    来源:掘金

  已知痛点
  在web页面登录的时候,很多小伙伴都会遇到这个问题,登录的时候,需要输入图片中的验证码,验证通过之后才登录成功;往往一些操作,都是需要登录之后才能往下操作,这对我们进行接口测试(接口自动化、UI自动化)产生了极大的困扰。

  痛点解决方案
  ·测试环境无所谓,直接叫开发改成万能验证码,或者测试环境关闭验证码验证
  · 使用Python OCR库进行识别,如tesserocr
  · 使用第三方 OCR服务(api),例如阿里云、百度云、腾讯

  方案分析
  改一下代码或者配置文件即可屏蔽验证码,测试环境无所谓,线上根本不行,此方案可作为备用方案。
  通过tesserocr库去识别验证码,前期需要我们学习一下这个库相关的api,未知领域探索,可能需要花较长时间~此方案作为备用方案。
  调用第三方OCR服务,通常都会完善的API文档或者对应的SDK,第三方OCR识别成功率还可以,此方案推荐。

  方案选择
  我这边选择了方案3,第三方 OCR服务(百度云),最主要是集成SDK,下载SDK即可调用,而且还是免费。

  方案实现过程(rap2登录)
  rap2登录时要输入验证码,我们通过百度OCR识别这个验证码,通过请求登录接口(账号+密码+验证码)模拟前端向后台发起请求,获取登录态后,再获取接口文档数据。

  OCR服务申请
  百度智能云地址:login.bce.baidu.com/
  首先我们去到百度智能云里,在左边菜单栏的产品服务中搜索"文字识别",点击【领取免费资源】,将所有的免费资源领取,领取之后要半个小时之后才能生效。
  回到主面板,我们要进行创建应用,填写相关的信息即可创建成功,应用创建好之后会生成AppID、API Key和Secret Key,注意这3项不要告诉别人哦!

  阅读官方文档
  文字识别官方文档:cloud.baidu.com/doc/OCR/ind…
  点击应用名称,查看该应用详情,里面有个查看文档,我们先可以看看是怎么用的。
  里面有两种方式,一种是API,另一种是SDK。

  识别demo
  先来识别这张图片试试,看了一下官方的SDK demo,少量代码即可实现识别功能,先通过pip install baidu-aip下载SDK,按照官方demo测试一下:
config = random.choice(OCR_CONFIG)
client = AipOcr(config['app_id'],config['api_key'],config['secret_key'])
options = {}
options["language_type"] = "ENG"
options["detect_language"] = "true"
with open(f"{IMG_PATH}/code.jpg", 'rb') as img:
    #调用百度OCR SDK,这里我用的高精度版,通过传入图像数据
    #你也可以用这个方法basicGeneralUrl,直接传入图片url
    code_data = client.basicAccurate(img.read())
    print(code_data)
打印输出:{'words_result': [{'words': ' HdAX'}], 'log_id': 1421303125069946686, 'words_result_num': 1}

  这里有几个踩坑点,要注意下:
  image,图像数据、base64编码,base64编码后大小不超过4M,最短边至少15px,最长边最大4096px,支持jpg/png/bmp格式。
  url,图片完整URL,URL长度不超过1024字节,URL对应的图片base64编码后大小不超过4M,最短边至少15px,最长边最大4096px,支持jpg/png/bmp格式。
  识别回来的验证码有可能跟图片的验证码不一致。
  有可能无法识别,接口直接返回空数据。
  有可能返回来的验证码结果是带有空格的。

  rap2登录实战
  首先我们去到登录页面,用F12看看验证码是怎么生成的,发现验证码是通过一个图片url随机生成的。那我们直接使用这个方法basicGeneralUrl,直接传入图片url试试,发现跟本调不通,出现报错:
url = 'https://rap2api.xxxx.com.cn/captcha?t=1626914290792'
code_data = client.basicGeneralUrl(url=url)
print(code_data)
打印输出: {'log_id': 1421464435711407280, 'error_msg': 'image format error', 'error_code': 216201}

  通过查阅官方文档,得知是因为上传的图片格式错误,现阶段支持的图片格式为:PNG、JPG、JPEG、BMP,要进行转码~看到这里是不是慌了,先别慌,我们首先分析一下的图片到底是什么格式的。
  打开图片URL,右键另存为,发现这个验证码图片格式是SVG!!!呀,这把我坑进去了!那我们现在要转换一下思路,只能使用basicAccurate这个方法,先下载SVG格式图片,再转码成JPG格式后传入图像数据。SVG转码成JPG,可以用这个库 svglib。
  完整代码实现:
class Rap2Data(object):

    session = None

    @classmethod
    def rap_login(cls):
        config = random.choice(OCR_CONFIG)
        client = AipOcr(config['app_id'],config['api_key'],config['secret_key'])
        options = {}
        options["language_type"] = "ENG"
        options["detect_language"] = "true"
        cls.session = requests.session()
        img_content = cls.session.get(url=CODE_URL).content
        #下载验证码图片
        with open(f"{IMG_PATH}/code.svg", "wb") as f:
            f.write(img_content)
        # svg转jpg
        drawing = svg2rlg(f"{IMG_PATH}/code.svg")
        #保存jpg图片
        renderPM.drawToFile(drawing, f"{IMG_PATH}/code.jpg", fmt="JPG")
        with open(f"{IMG_PATH}/code.jpg", 'rb') as img:
            #调用百度OCR SDK
            code_data = client.basicAccurate(img.read())
            code_list = code_data.get('words_result', [])
            if code_list:
                #有时候结果存在空格
                code_str = code_list[0]['words'].replace(" ", "")
                RAP_ACCOUNT['captcha'] = code_str
                res = cls.session.post(url=RAP_LOGIN_URL, json=RAP_ACCOUNT)
                res_data = res.json()
                #验证是否登录成功,返回id即成功
                if res_data['data'].get('id', None):
                    return True

    @classmethod
    def rap_data(cls, id):
        #传入接口文档id,获取接口文档数据
        login_result = False
        #这里循环调用登录方法,判断是否登录成功,因为OCR识别并不是百分百成功的
        #这里之后要改一下,为了避免重复调用,用表存储cookies,cookies失效了,再重新获取
        while not login_result:
            login_result = cls.rap_login()
        params = {"id": id}
        res = cls.session.get(url=RAP_PROJECT_URL,params=params)
        return res.json()

  rap2登录大概是这样子的,通过验证码URL生成cookies,如果你登录成功了,这个cookies就是你的令牌,有了这个令牌你就可以访问接口文档。上述代码中,直接使用了session对象,不用每次请求都传入cookies。

  后续扩展
  解析接口文档数据,生成Excel格式的接口自动化用例或者yaml格式接口自动化用例。
  解析接口文档数据,生成jmeter脚本(jmx),再也不用一个个复制粘贴写脚本。
  基于上述功能,做成前端页面,供其他人使用。

  总结
  本期介绍了百度OCR的使用方法,更多使用场景可以结合自己的需求~

  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号