从零开始打造一个12306验证码识别系统

12306验证码从简单的数字图片验证码进化到图形识别验证码,成功拦住了需要购票的民众,但并没有拦住机器,今天我们用一篇文章讲解如何从零开始设计并实现一套12306验证码识别系统,所有思路已成功实现并达到一张图片验证码300ms内识别完成并到12306网站验证通过。

问题分析

12306图片包含以下两种图片:
包含两个问题的图片验证码:
包含两个问题的图片(在提交购票请求时问题时两个)
包含一个问题的图片验证码:
登录时出现的图片验证码问题一般时一个
图片中的信息包含两个部分,一部分是第一行的问题,如剪纸、话梅、棉棒等,另一部分是下半部分的图片,其中包含八张图片,其中每一张图片必定属于一个问题,且至少一个问题是第一行的问题,为了能够做到自动识别,需要做到,

1、识别出第一行的问题

2、找到下半部分每张图片属于的问题

3、在下半部分的的图片中找到属于第一行的问题的图片

当我们能使用机器做到上面的三个步骤时我们就能做到自动识别验证码了。

解决步骤

1、分离问题图片

通过观察发现每一张图片验证码的 请点击下图中所有的 这部分文字都是一样的,它的长度也是一样的,所以我们可以使用代码将前面公共部分去掉,只留下后面的问题部分(通过像素操作保留后面的问题部分生成一张新的图片)
在这里插入图片描述
在这里插入图片描述

2、确定问题个数以及分离出问题图片

因为验证码中的问题可能是1个,也可能是2个,所以我们需要能够识别出问题的个数(两个问题的图片问题部分背景一般是白色的,该张图片是12306识别到我请求次数频繁后返回的,所以我们处理背景是白色的就可以),通过观察我们发现两个问题相隔有一片空白部分,而且一个问题的多个字之间相隔比较紧密,所以我们可以通过像素(白色)探测来确定该图片是包含两个问题还是一个问题,假设使用一个横线从上到下,当该条线上存在非白色像素且中间包含白色像素(可以指定宽度)且向下移动时时白色像素连续则说明该验证码包含两个问题,我们可以选择非白色像素中间的白色像素的某一条线作为分离依据(一般选择中间连续白色像素的中点),将问题图片分离生成两个问题图片;如果探测时没有包含这种情况则说明该验证码图片只有一个问题。

3、通过其它方式识别问题图片中的问题

当我们拿到只包含问题的图片后就可以去识别上面的汉字了,可以选择光学识别,也可以选择使用机器学习技术来识别汉字,在实际操作过程中发现光学识别不能很好的识别出汉字,因为12306返回的图片上的汉字有各种奇形怪状且相连比较紧密,我使用的是机器学习的方式,通过对一批图片进行标注后使用机器学习生成模型(可能需要比较多的标注图片,我选择的是第三方打码平台,把图片传到平台,平台返回上面的汉字,机器学习参考文章
),当图片标注比较多且类型比较全时能达到99%的准确率。
在这里插入图片描述

4、分离下半部分的图片

我们拿到验证码的问题后需要知道下半部分的哪些图形属于该问题,所以需要先将下半部分的多个图形分离成只包含一个图形的单张图片,通过观察发现每张的图片的大小都一样,所以通过计算出每个图片坐标后使用硬编码的方式分离出图片,推荐使用windows自带的图片工具查看像素坐标。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5、识别图形分类

如果我们刚开始可能没有任何一张图片的分类数据,这时我们依然可以选择第三方打码平台进行图片标注积累原始数据,当我们已经有了一批数据积累后可以选择答案探测方式,这里有一个比较关键的点是如何确定两张图片是同一张图片,也就是拿到一张图片后如何从我们的已有数据里寻找这张图片并拿到它的分类,推荐使用phash算法,该算法将一张图片转换为50位的0、1字符串,如何通过计算两张图片生成的字符串的汉明距离来确定两张图片的相似度(因为场景比较特殊,可以将距离值设为3,大于3则不是一张图片),使用这种方式时推荐使用elasticsearch将图片索引,搜索时使用字符匹配搜索方式(设置最小匹配数为47)进行搜索来寻找相同图片,也可以直接对图片进行md5,当两张图片的md5一样时则是同一张图片(这种方式需要在进行图片分离时保证这张图片在图片的不同位置时分离出的图片的md5一样),使用这种方式时则可以直接数据库进行保存和查找,非常方便。

6、生成答案

确定每一个图形的分类后即可与问题进行对比,选择分类一样的图形并使用该图形在图片中的坐标生成答案,使用该答案调用12306的验证接口进行验证,如果通过则可以直接登录或时提交购票请求,否则重试即可。
每一个图形都有确定的分类可能是比较理想的情况,更多可能其中一个或多个图形属于未知分类,甚至所有图形都属于未知分类,这里可以使用推测法,基于已知图形分类和未知图形分类生成所有推测的答案,并将这些答案列表与该验证码图片关联(将完整的图片验证码以及特征存储到数据,方便下次遇到同一张图片时查找),然后从推测的答案列表中选择一个答案到12306进行验证,当验证不通过时抛弃该答案,等待下次遇到相同图片时再从剩余答案中选择一个答案,直到一个答案成功。当拿到一个成功答案时可以将不属于答案的图形进行标记,标记该图形肯定不属于这张验证码图片的问题(一个分类或两个分类),同时将作为答案的图形进行标记(如果问题是一个分类时该图形分类已确定,否则将该图形标记可能是这两个分类,或者基于已有的可能标记直接确定图形分类),下次其它图片生成推测答案时可以参考该标记,生成更少的推测答案列表,甚至直接生成正确答案,这样我们可以定时请求12306验证码接口进行图形分类学习,如果所有图形分类都已确定则我们的库能做到不用进行验证码重试,因为12306定期放出新图形,这要求我们需要不断进行学习。

按照以上步骤实现的12306验证码识别程序真实可用,现在还能想起那些彻夜写代码的夜晚。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值