前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >尝试绕过验证码

尝试绕过验证码

作者头像
赵云龙龙
发布2020-06-16 15:13:20
7880
发布2020-06-16 15:13:20
举报
文章被收录于专栏:python爱好部落python爱好部落

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

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

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

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

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

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

代码语言:javascript
复制
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/ 然后安装:

代码语言:javascript
复制
python -m pip install --upgrade pip
pip3 install tesserocr pillow

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

代码语言:javascript
复制
def test():


    image = Image.open(image_path)

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

    return str(text)

可能会出错:

代码语言:javascript
复制
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次。

代码语言:javascript
复制
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呢。

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 python粉丝团 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
文字识别
文字识别(Optical Character Recognition,OCR)基于腾讯优图实验室的深度学习技术,将图片上的文字内容,智能识别成为可编辑的文本。OCR 支持身份证、名片等卡证类和票据类的印刷体识别,也支持运单等手写体识别,支持提供定制化服务,可以有效地代替人工录入信息。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档