从“冲顶大会”自动答题到对教务处登陆图片验证码的自动识别

今天接着对前面的教务处爬取信息的脚本进行完善。

到目前为止,前面已经实现了对内容的获取以及对获取信息的可视化整理,但是有一点没有解决,就是每一次登录都需要我们自己手动查看本地文件,并且输入验证码。

一段代码的诞生,其目的就在于能让使用者感受到进一步的便捷和高效,那我们能不能将验证码这一步省略过去呢?这个时候,我想到了之前很火的“冲顶大会”类的自动答题脚本,答题的时候是能自动识别屏幕上的相关文字的,那我是不是也可以以此类推,自动识别教务处的图片验证码呢?答案是肯定的。

通过查看github上的相关项目,我发现,一般识别图片上的文字,有两种方式:

第一种:通过Tesseract-OCR进行识别。

优点:调取本地文件,无次数限制,并且具有很多文字库和文字学习功能。

缺点:成本比前者高,需要下载本地模块,使用者必须在自己机器上面安装。


在安装好了Tesseract-OCR后,配置环境变量,这几步可以参考

https://jingyan.baidu.com/article/219f4bf788addfde442d38fe.html

将我们的验证码用命令行测试,发现问题:识别出来的是个小白框。

接着自己弄了一张图片,发现识别成功。因此考虑是图片本身影响了识别,经过多次的尝试,发现是图片中文字本身太小的缘故。

如果还要对图片进行灰度处理,我觉得很麻烦,因此放弃这个方法,尝试用别的识别引擎。

第二种:通过调取百度aip进行识别。

优点:成本比较低,只需要取百度的开发者平台申请一个相应的接口密钥。

缺点:每天的可识别次数有上限,目前是每人五百次。

调取aip接口之后,post相应的密钥信息,将本地的验证码图片上传并下载,返回imgresult,初步实现代码如下:

def get_image_content(imgpath):
    with open(imgpath,'rb') as fp:
        return fp.read()
options = {
    'detect_direction': 'true',
    'language_type' : 'CHN_ENG',
}
imgresult = aipOCR.basicGeneral(get_image_content(imgpath),options)
print(json.dumps(imgresult))

发现返回结果正确。此时发现返回的content其实就是前面代码获取的验证码requests.get().content,正好避免了"wb" 和“rb”的操作。原来的代码:

captcha = requests.get('http://run.hbut.edu.cn/Account/GetValidateCode', headers=headers)
result = captcha.content
imgpath = 'F:\新建文件夹\python\验证码\hugongda.jpg'
fn = open(imgpath,'wb')
fn.write(result)
fn.close()
def get_image_content(imgpath):
    with open(imgpath,'rb') as fp:
        return fp.read()
options = {
    'detect_direction': 'true',
    'language_type' : 'CHN_ENG',
}
imgresult = aipOCR.basicGeneral(get_image_content(imgpath),options)
print(json.dumps(imgresult))

改善之后的代码:

options = {
    'detect_direction': 'true',
    'language_type' : 'CHN_ENG',
}
captcha = requests.get('http://run.hbut.edu.cn/Account/GetValidateCode', headers=headers)
imgresult = aipOCR.basicGeneral(captcha.content,options)
print(json.dumps(imgresult))
这个时候,发现print出来的结果是类似于字典的值,但是当我们用字典进行取值的时候,却发现无法取出,经过思考,发现问题是:虽然返回的是一段类似于字典的玩意儿,但是那个东西本质上是字符串,这个时候我们利用eval方法将字符串转为list,并以数组的方式取出中间的验证码值。

a = eval(json.dumps(imgresult))['words_result']#json.dumps传回的参数为字符串,转为list

想要实现自动输入验证码,我们就需要传值。将字符串的无关内容处理掉,接下来就是需要post的data了。(这里的要点是要将list对象a转换成string对象才能处理。)

有时候会识别错误,于是写一个循环,直到成功为止。

def login():
    xuehao = input('请输入您的学号:')
    mima = input('请输入您的密码(初始为身份证后八位):')
    data = {
        'isRemember': '1',
        'Password': mima,
        'Role': 'Student',
        'UserName': xuehao,
        'ValidateCode': getCode(),
    }
    response = requests.post('http://run.hbut.edu.cn/Account/LogOn', data=data, headers=headers)
    if '验证码错误' in response.text:
        error = input('获取失败,是否重新发送请求?(Y/N)\n中止程序请按n')
        if error == 'y' or 'Y':
            print('正在重新获取您的成绩...')
            login()
    else:
        gradeHander()

结果:


完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值