专栏首页python爱好部落尝试绕过验证码

尝试绕过验证码

最近出了点安全事故,有人盗号。而且手段极其简单,就是暴力破解。 为了提高安全性,UI的界面加了验证机制。这也为自动化测试提高了难度。

按照一般的做法,是先截取页面的图,然后通过坐标位置,来定位验证码的位置,然后截取验证码。 效果如下

我首先想到的是,通过mitmproxy拿到图片的url来获取图片,进而来识别图片的文字,发现那url,每次请求都会变化。

于是只能用截图的方式了。

对于web来说,可以通过元素,根据attribute来获取URL,来获取验证码图片,并将图片放大,这样识别的效果更好。

对于App来说,如果不能通过URL来获取,那只能通过截图的方式来碰碰运气了。 以下是App的方式。

driver.save_screenshot("login.png")
captcha=driver.find_element_by_xpath("//android.view.View[3]/android.widget.Image")
left = captcha.location['x']  # 区块截图左上角在网页中的x坐标
top = captcha.location['y']  # 区块截图左上角在网页中的y坐标
right = left + captcha.size['width']  # 区块截图右下角在网页中的x坐标
bottom = top + captcha.size['height']  # 区块截图右下角在网页中的y坐标

picture = Image.open(r'login.png')
picture = picture.crop((left, top, right, bottom))  # 二次截图:形成区块截图
imgry = picture.convert('L')  # 图像加强,二值化
sharpness = ImageEnhance.Contrast(imgry)  # 对比度增强
sharp_img = sharpness.enhance(2.0)
sharp_img.save(r'captcha.png')
code = test()
print(code)

图片有了,怎样识别文字能,用OCR来识别,可以去这里下载一个 https://digi.bib.uni-mannheim.de/tesseract/ 然后安装:

python -m pip install --upgrade pip
pip3 install tesserocr pillow

运行以下代码来识别图片。

def test():


    image = Image.open(image_path)

    text = pytesseract.image_to_string(image)  # 使用简体中文解析图片
    print(str(text))

    return str(text)

可能会出错:

pytesseract.pytesseract.TesseractNotFoundError: tesseract is not installed or it's not in your path

解决方法: 1.找到python的安装路径下的pytesseract: 例如我的是 E:\Python3\Lib\site-packages\pytesseract

2.用文本编辑器打开,查找tesseract_cmd

将原来的 tesseract_cmd = 'tesseract' 改为: tesseract_cmd = 'OCR的安装路径下的tessract.exe'

例如我的是 tesseract_cmd = 'C:\Program Files\Tesseract-OCR\tesseract.exe' 然后运行,就成功了。 等一下,发现运行很多次,有的时候能够完全识别,有的时不能,识别率真的不高。现在还是很简单的情况下,如果更多干扰,那更不行了。

于是在网上搜索提高识别率的,比如增加灰度等,还是没什么用,最后听说搞AI识别,能训练啥的,就用了一个百度AI识别的,一天免费500次。

import requests
import json
import base64
import time


class baiduCode(object):

    @classmethod
    def get_token(cls):
        """
        当前函数只用调用一次,用来获取当前账号的token
        :return:
        """
        # 标记当前精准识别是否使用完
        cls.curr_url = ''
        cls.basic_flag = False
        cls.max_num = 100
        cls.login_url = 'https://aip.baidubce.com/oauth/2.0/token'
        cls.login_params = {
            'grant_type': 'client_credentials',
            'client_id': 'wAIXfXOUS8ztLa4FrK3rZex1',
            'client_secret': '3b8nvjSGUZq0LPC18VVAizKYRBbny6Mq'
        }
        cls.headers = {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
        response = requests.post(cls.login_url, params=cls.login_params, headers=cls.headers)
        result = json.loads(response.text)
        cls.token = result['access_token']

    @classmethod
    def get_code(cls, path='', url=''):
        cls.num = 0
        # 普通图片识别的请求链接,正确率50%(测试了500张图片)
        cls.general_basic_url = 'https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic'
        # 高精度图片识别的请求链接,正确率80%(测试了500张图片)
        cls.accurate_basic_url = 'https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic'
        if path:
            if not cls.basic_flag:
                cls.curr_url = cls.accurate_basic_url
            with open(path, 'rb') as f:
                base64_data = base64.b64encode(f.read())
                base = base64_data.decode()
                cls.basic_params = {
                    'image': base,
                    'access_token': cls.token
                }
        elif url:
            cls.curr_url = cls.general_basic_url
            cls.basic_params = {
                'url': url,
                'access_token': cls.token
            }
        else:
            raise ValueError('当前path和url参数均错误')
        time.sleep(0.5)
        while True:
            try:
                response = requests.post(cls.curr_url, params=cls.basic_params, headers=cls.headers)
                result = json.loads(response.text)
                # 判断当前精准识别是否被使用完
                try:
                    result['words_result']
                except Exception as e:
                    print(e)
                    cls.num += 1
                    if cls.num > cls.max_num:
                        raise ValueError('当前尝试的错误次数超过%d次,请重新调用'%(cls.max_num))
                    cls.basic_flag = True
                    cls.curr_url = cls.general_basic_url
                    continue
                code = result['words_result'][0]['words']
                return code
                break
            except Exception as e:
                print('error: ', e)
                cls.num += 1
                if cls.num > cls.max_num:
                    raise ValueError('当前尝试的错误次数超过%d次,请重新调用'%(cls.max_num))


if __name__ == '__main__':
    # 当前获取token的函数只用调用一次
    baiduCode.get_token()
    # 直接传图片的地址就好
    image_path = "C:\\work\\code\\android\\captcha.png"
    code = baiduCode.get_code(path=image_path)
    print(code)

用起来效果不好,还不如OCR呢。

看来得想别的方法绕过去了。

本文分享自微信公众号 - python粉丝团(pythongroup),作者:捧个场呗

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-06-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 基本算法-分而治之

    第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加;

    赵云龙龙
  • cypress搭建自动化框架

    在简单看了cypress 官方文档后,就开始用上了,越用感觉越爽。 顺便提一句,官方文档太良心了,方方面面都讲到了,而且还有视频,可以切换语言。 下面就...

    赵云龙龙
  • python处理testlink

    在软件活动中,我们需要对测试用例进行管理,如果只用excel,不用管理工具系统的管理,那么将出现以下一些问题: 案例文件分散,测试进度不透明; ...

    赵云龙龙
  • 在Python中实现单例模式

    有些时候你的项目中难免需要一些全局唯一的对象,这些对象大多是一些工具性的东西,在Python中实现单例模式并不是什么难事。以下总结几种方法: 使用类装饰器 ...

    Jetpropelledsnake21
  • Python中的单例模式

    单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个...

    py3study
  • “单例模式有四样写法,你知道么?”——孔乙己

    单例模式(Singleton Pattern)是最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

    BigYoung小站
  • Lua(3) ——Cocos之_语法糖c

        在使用Lua的时候,cocos2d-x为我们提供了一个 class(classname, super) 这个函数。

    py3study
  • 答疑《python的CLS》

    这两天有个朋友看到这样的一个代码,问我啥意思,我第一眼看上去也是比较懵的(原谅我比较菜,见识短),cls后面竟然多了个括号???,直接开始用了????

    我被狗咬了
  • 欧拉计划——38全数字的倍数

    连接这些乘积,我们得到一个1至9全数字的数192384576。我们称192384576为192和(1,2,3)的连接乘积。

    lop
  • 码仔精心整理的“70道”常问面试题

    将一个请求封装为一个对象,从而使用户可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

    用户1564362

扫码关注云+社区

领取腾讯云代金券