文章目录

  • 前言
  • 一、验证码数据集获取
  • 二、图像处理
    • 2.1 验证码图片转灰度、二值化、去噪点
    • 2.2 对图像进行切割
    • 2.3 批量处理图片数据
  • 三、图像特征提取
    • 3.1 所有图像特征值提取
    • 3.2 单张图片特征值提取
  • 四、模型训练
  • 五、实际测试

前言

之前写了一个正方教务系统登录的程序,当时验证码使用的是手动输入,觉得太煞笔了,这种用途的脚本怎么可以让这种小小验证码拦住呢!︿( ̄︶ ̄)︿,我们要的可是完全不要人工的爬虫啊!你可知道!┑( ̄Д  ̄)┍

有想法很好,我们就开始做吧!

一、验证码数据集获取

这里我从github上下载了数据集,大概五百张图片,非常感谢其提供者。

数据集我放在我的源码里面了,需要的话,可以自行下载,github链接在底部,此处不赘述。

二、图像处理

2.1 验证码图片转灰度、二值化、去噪点
def GrayscaleAndBinarization(image):'''灰度并二值化图片:param image::return:'''threshold = 17  # 需要自己调节阈值,17效果不错哦!tmp_image = image.convert('L')  # 灰度化new_image = Image.new('L', tmp_image.size, 0)# 初步二值化for i in range(tmp_image.size[1]):for j in range(tmp_image.size[0]):if tmp_image.getpixel((j, i)) > threshold:new_image.putpixel((j, i), 255)else:new_image.putpixel((j, i), 0)# 去噪,去除独立点,将前后左右等九宫格中灰度通道值均为255的像素点的通道值设为255for i in range(1, new_image.size[1] - 1):for j in range(1, new_image.size[0] - 1):if new_image.getpixel((j, i)) == 0 and new_image.getpixel((j - 1, i)) == 255 and new_image.getpixel((j + 1, i)) == 255 and \new_image.getpixel((j, i - 1)) == 255 and new_image.getpixel((j - 1, i - 1)) == 255 and new_image.getpixel((j + 1, i - 1)) == 255 and \new_image.getpixel((j, i + 1)) == 255 and new_image.getpixel((j - 1, i + 1)) == 255 and new_image.getpixel((j + 1, i + 1)) == 255:new_image.putpixel((j, i), 255)return new_image
2.2 对图像进行切割

在训练之前,我们需要获取每个字符的数据,作为训练集,所以我们把验证码中的字符切割开来。之前我还使用算法进行检测切割位置,后来发现完全没有必要啊!(=。=),验证码中总共四个字符,我用手指一比,其中每个字母都处于大致区间内,这就简单了我们的工作,我们只要在固定的区间内进行切割,就能保证四个字符能够完好的被分开。

def SplitImage(image):'''切割图像并保存,关键在于寻找切割位置:param image::return:'''splitSite = [0, 16, 28, 41] # 这个位置非常好,nicesplitSite.append(54)# 对图片进行切割new_image = []for index in range(1, len(splitSite)):box = (splitSite[index - 1], 0, splitSite[index], image.size[1])new_image.append(image.crop(box))return new_image
2.3 批量处理图片数据

下面的是数据集文件夹。

首先我们写一个函数获取该文件夹下验证码文件的文件名,作为标签。

def GetFileName(filePath):'''返回指定文件夹下文件的文件名:param filePath::return:'''filenames = []for filename in os.listdir(filePath):filenames.append(filename)return filenames

接下来我们批处理所有图片

def SplitAllImage():'''分割所有图片:return:'''# dict 记录每个字符的数目dict = {'0': 0, '1': 0, '2': 0, '3': 0, '4': 0, '5': 0, '6': 0, '7': 0, '8': 0, '9': 0,'a': 0, 'b': 0, 'c': 0, 'd': 0, 'e': 0, 'f': 0, 'g': 0, 'h': 0, 'i': 0, 'j': 0, 'k': 0, 'l': 0, 'm': 0, 'n': 0,'o': 0, 'p': 0, 'q': 0, 'r': 0, 's': 0, 't': 0, 'u': 0, 'v': 0, 'w': 0, 'x': 0, 'y': 0, 'z': 0}filenames = GetFileName('./images/data_biaoji')for item in filenames:  # 图片名称image = Image.open('./images/data_biaoji/{}'.format(item))tmp_image = GrayscaleAndBinarization(image)data_image = SplitImage(tmp_image)for i in range(len(data_image)):  # 此处值为4,对切割后的四张图片进行处理dict[item[i]] = dict[item[i]] + 1data_image[i] = data_image[i].resize((14, 27))data_image[i].save('./images/data/{}/{}.jpg'.format((item[i]), dict[item[i]]))  # 总共获取了1884张图片print(dict)

三、图像特征提取

机器如何能够识别图像的呢?当然是转化为机器识别的数字啊!这时我们将经图像处理后的图片进行特征提取,将各个像素的通道值提取到一个列表中。

3.1 所有图像特征值提取
def returnDataAndLabel(path='./images/data'):'''返回全部数据:param path: 图片路径:return: data 和 label'''raw = []datas = [] # 特征labels = []        # 标记for item1 in os.listdir(path):  # 文件路径label = item1for item2 in os.listdir(path + '/' + item1):data = []image = Image.open(path + '/' + item1 + '/' + item2).resize((14, 27))for i in range(image.size[1]):  # 读取像素通道值for j in range(image.size[0]):data.append(image.getpixel((j, i)))data.append(label)  # 一张图片的数据if len(data) == (14 * 27 + 1):  # 图片尺寸raw.append(data)for i in range(len(raw)):tmp_data = raw[i][: -1]tmp_label = raw[i][-1]labels.append(tmp_label)datas.append(tmp_data)return datas, labels
3.2 单张图片特征值提取
def featuretransfer(image):'''返回特征向量,预测时用:param image: 图像:param label: 图像所属标签:return: 特征向量'''features = []image = image.resize((14, 27))for i in range(image.size[1]):for j in range(image.size[0]):features.append(image.getpixel((j, i)))return features

四、模型训练

集成学习较一般学习器往往有较好的效果,此处使用了随机森林算法

def trainModel(datas, labels, isSave=True, path='./model/clf1.model'):'''训练模型:param datas: 数据集:param labels: 标签:return: 模型'''X_train, X_test, y_train, y_test = train_test_split(datas, labels, test_size=0.3, random_state=30)clf = RandomForestClassifier(n_estimators=500, max_depth=10, min_samples_split=10, random_state=0)clf.fit(X_train, y_train)y_pred = clf.predict(X_test)score = accuracy_score(y_test, y_pred)print('Accuracy score:', score)if isSave:joblib.dump(clf, path)return clf

ps: 最后发现效果不错,单个字符识别正确率能达到84%多,模型没有调参,有兴趣的同学可以继续调节使准确率更高。但这里我又想到了一点,单个字符识别率有84%,但正方验证码有四个字符,准确率那就是84%*84%*84%*84% = 0.49,妈呀!识别率一下降了这么多,能用吗??

五、实际测试

测试主要使用正方教务系统进行登录进行实际测试,这里有关爬虫,就不细说了,登录代码摆上!!!

import requests
from pyquery import PyQuery as pq
from urllib import parse
from sklearn.externals import joblib
from ProcessingImage import *   # 自定义模块
import re
import jsonclass SCHOOL(object):def __init__(self):self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0',}self.username = '**********'  # 学号self.password = '**********'  # 密码self.name = ''self.url_base = 'http://***.***.***.***/'  # 这里换成自己学校的地址self.raw_url = self.url_base + 'default2.aspx'self.url_1 = ''self.login_url = ''self.real_url = ''self.session = requests.Session()self.get_real_url()self.login()def get_real_url(self):'''获取真实的登录url:return:'''response1 = self.session.get(self.raw_url, headers=self.headers)self.login_url = response1.urlself.real_url = re.match('(.*)\/default2.aspx', self.login_url).group(1)self.url_1 = self.real_url + '/xs_main.aspx?xh=' + self.usernamedef loadModel(self, filename):return joblib.load(filename)def login(self):'''登录过程:return:'''response2 = self.session.get(self.login_url, headers=self.headers)text = response2.textdoc = pq(text)get_captcha_src = doc.find('#icode').attr("src")_VIEWSTATE = doc.find('#form1 input').attr("value")_VIEWSTATEGENERATOR = doc.find("#form1 input[name='__VIEWSTATEGENERATOR']").attr('value')captcha_url = self.real_url + '/' + get_captcha_srccaptcha = self.session.get(captcha_url).content# 保存验证码with open('./test/captcha.jpg', 'wb') as f:f.write(captcha)model = self.loadModel('./model/clf1.model')   # 导入模型img = Image.open('./test/captcha.jpg')new_img = SplitImage(GrayscaleAndBinarization(img))# 模型预测验证码result_pred = []i = 0for item in new_img:tmp = []item.save(str(i) + '.jpg')i = i + 1img_after_split = item.resize((14, 27))tmp.append(featuretransfer(img_after_split))result_pred.append(model.predict(tmp)[0])captcha = ''.join(result_pred)print('此次预测结果为:', captcha)# 登录过程post_data = {'__VIEWSTATE': _VIEWSTATE,'__VIEWSTATEGENERATOR': _VIEWSTATEGENERATOR,'Button1': '','hidPdis': '','hidsc': '','IbLanguage': '','RadioButtonList1': '%D1%A7%C9%FA','Textbox1': '','TextBox2': self.password,'txtSecretCode': captcha,'txtUserName': self.username}response3 = self.session.post(self.login_url, headers=self.headers, data=post_data)self.name = pq(response3.text).find('#xhxm').text().replace('同学', '')if '欢迎您:' in response3.text:print('登录成功!', self.name)else:print('登录失败!正在尝试重新登录')

此处我进行了一百次测试,结果还不错哦!虽然准确率只有大概50%,但经不住程序跑的快啊,对于这个模型,基本3次以内就能成功识别验证码。

Github链接:https://github.com/kingdowliu/IdentificationCodesOfZhengFang

感谢支持!敬礼!!

正方验证码智能识别及教务系统模拟登录相关推荐

  1. 新版正方教务系统模拟登录登录密码RSA加密破解

    新版正方教务系统模拟登录登录密码RSA加密破解 最新版本教务系统,登录密码有被RSA加密,模拟登录时,我们需要先正方教务的加密方式. 第一步:获取到加密公钥 通过抓包我们可以获取到公钥获取url,然后 ...

  2. 教务系统模拟登录与成绩爬取一

    版权声明:本文为博主原创文章,转载 请注明出处 https://blog.csdn.net/sc2079/article/details/82563854 -写在前面 暑假期间学校的学生教务系统大改, ...

  3. 详解教务系统模拟登录与爬取二

    版权声明:本文为博主原创文章,转载 请注明出处:https://blog.csdn.net/sc2079/article/details/82564284 - 写在前面 上篇博客教务系统模拟登录与成绩 ...

  4. 基于HttpClient的正方教务系统模拟登录(带验证码)

    PS:恩,由于最近在学web和简单的http协议,所以心血来潮想用java写个爬虫来爬取学校官网(正方教务系统)个人主页的基础信息(课程信息.成绩--),其实在之前学过java基础教程的时候就可以写的 ...

  5. 广金强智教务系统模拟登录

    文章目录 网站首页 表单提交 java实现加密 验证结果 验证码问题 登录请求 网站首页 表单提交 f12查看提交发现有encodeInp()加密字符串 java实现加密 conwork.js var ...

  6. 滑块拖动验证码智能识别验证码技术(持续更新)

    众所周知,验证码是用来防机器的.但是,随着神经网络的发展,近几年验证码难度持续上升,这玩意儿的存在存粹就是一种负担,特别是国内到处都是的[Ji验].本文针对"J验"及其他类似验证方 ...

  7. 浙大教务网登录验证码自动填充--chrome插件开发

    浙大教务网登录验证码自动填充--chrome插件开发 一.前言 二.验证码图像识别 三.chrome插件开发 四.插件使用和结果展示 五.未来展望 六.提示 一.前言 女朋友说"教务网每次登 ...

  8. python---POST/GET请求数据包,图片验证码自动化识别,pytesseract,模拟用户一次正常登录

    python-POST/GET请求数据包,图片验证码自动化识别,pytesseract 项目内容: 模拟用户正常登录Binzcms系统,对登录Binzcms系统进行自动化识别图片验证码,使用get与p ...

  9. 数据抓包(网络爬虫)-正方教务管理系统登录后获取自己的课程表

    上次发的博客是:数据抓包(网络爬虫)-正方教务管理系统登录 好的,今天我们来抓自己的课程表数据,说实话,都会模拟登录了,抓个课程表的什么就不再话下了. 直接来步骤: 1.首先还是监视浏览器中得到自己课 ...

最新文章

  1. 一个让Python代码运行更快的最佳方式!
  2. multiprocessing python_Python多进程运行——Multiprocessing基础教程1
  3. JSP页面EL表达式不解析
  4. git中文件的三种状态
  5. java customerservlet_顾客管理系统java+servlet
  6. 深度学习之卷积神经网络 VGGNet
  7. java 使用 lamba 表达式处理二维数组
  8. 所有浏览器的 CSS selectors 兼容性
  9. cad安装日志文件发生错误_Autocad 2012 安装失败,某些产品无法安装。有日志文件,拜托求大神帮忙看看如何解决?...
  10. 渥太华大学计算机科学,【加拿大渥太华大学计算机科学排名第四】渥太华大学录取条件...
  11. 关于路由器和交换机的区别图解(总结)
  12. Excel快速拆分单元格内容
  13. 从零学习node爬虫
  14. 润生香港轻零食之品牌零食合作 I 专业·共赢·美味
  15. 黑马程序员---IT行业调查报告
  16. 【Azure Data Platform】ETL工具(8)——ADF 数据集和链接服务
  17. macbook 连接不上蓝牙鼠标 m585 m590 解决方法
  18. dg备库怎么逻辑导出exp/expdp?
  19. 主流mes厂商_国内主流MES厂商排名报告
  20. 英首相:比起无协议脱欧 国会阻挠脱欧可能性更高

热门文章

  1. 从零实施ERP如何成功
  2. 精益质量管理简析(转载)
  3. css 弹性盒子 flex布局
  4. Vue-Springboot前后台访问端口不一致
  5. Java面试官:java高级工程师简历csdn
  6. git 使用meld 进行文本对比
  7. HTML径向效果,HTML Canvas实现径向渐变效果
  8. 【LeetCode-SQL】196. 删除重复的电子邮箱
  9. python数据分析前景如何_数据分析师的前景怎么样?
  10. Android camera2 框架学习记录