Python解析最简单的验证码


Posted in Python onJanuary 07, 2016

最近在学python,正好遇到学校需要选宿舍,就用python写了一个抢宿舍的软件。其中有一个模块是用来登陆的,登陆的时候需要输入验证码,不过后来发现了直接可以绕过验证码直接登陆的bug。不过这是另外的话题,开始的时候我并没有发现这个隐藏起来的秘密,所以我就写了这个python代码段用来实现解析验证码的功能。

我们学校的验证码是最简单的验证码,形式大概如下:

Python解析最简单的验证码

其中这个图片的大小是60X24像素的,大概每个数字的大小是15X24像素。

观察这个验证码之后可以发现,验证码中只有数字而且数字的字体很规范,只不过每个数字的颜色不同而已。

当时有2个思路

1.将整张照片平均切片成四分,每个数字一个图片,然后扫描每张照片的每个像素,为每个数字初始化一个特征码buff,大小为15X24的byte,即总共45Byte。

先取背景色,可以知道(0,0)位置是背景色。然后扫描数字的每个像素和背景色对比如果相同则为1不同则为0。然后分析出0-9这10个字符的特征值。等需要解析验证码的时候直接将验证码图片分片取特征值跟标准特征值对比就可以了。

2.我们可以想象0-9这10个字符每个字符的字形都不一样,则有可能比如9这个数字在像素(2,12)(1,13)这个位置是独有的,也就是说分片图片中假如(2,12)位置的像素点和背景色一致,则该分片图片一定不是9否则一定是9。

  上面两种方法有一个bug就是这个图片的第一个数字有一定的偏移,比如其他位置的数字是从第3列开始的,它可能从第4列,这个我就没具体分析了。不过这个也有办法解决,我用的办法就是从第一列非背景色的地方算起。不管什么图片怎么偏移,它x轴向对于自己最左边的点的x方向的差值是不变的。

最后我的实现方法就是按第二种,因为这种方法是最快的,只需要取特征像素处的点就可以。

我的方法是这样的,首先选用材料图片三张,包含0-9这10个字符,然后校验他们每个像素与背景色是否一致,如果一致则把这个数字放到对应这个像素的hash表里面。

最后分析这个hash表找出哪个像素是1个数字独有的,哪个像素是2个数字独有的,哪个像素3个数字独有的,最后解析这个表。

找到可以唯一确定一个数字的方法,比如(0,18),(0,19)这两个数字可以唯一确定数字1。

然后得出一个hash字典:

NumberKeyPixel={
[(7,10),(0,12),(0,10),(0,11),(0,8),(1,14),(1,15)],
[(4,8)],
[(0,18),(0,19)],
 [], 
[(5,7)],
[(0,4),(0,10)],
[(2,6)],
[(2,16)],
[(0,12)],
[(2,13)]
}

使用的时候,只需依次比对这些像素点就可以判断这张图片的验证码值了。

下面介绍具体代码

1.首先是分析的时候的代码,用来获得数字的特征像素:

from PIL import Image
import os
#存放材料图片的路径
path="C:\\vaildpic\\"
#取得材料图片
images=os.listdir(path)
存放数字的切片,0-9的图片
nubimgs=[]
#存放背景色
backpixels=[]
#存放像素对应表
pixDir={}
#首非背景色偏移值
pixBlankEndPos=[]
#这个函数用来取得这个图片中数字结构的偏移值
def GetLastBlankPosition(materialPic,x=0):
bc=materialPic.getpixel((0,0))
for i in range(15):
for j in range(24):
if materialPic.getpixel((i+x,j))!=bc:
return i
#因为只是解析没有写的很严谨,这个地方
#取得目标文件夹的图片
for image in images:
if os.path.isdir(path+image):
continue
image=Image.open(path+image)
#对于每张图片切成四份,存到字典中,取得相应的背景色,首非背景色偏移x,接下来计算用
for i in range(4):
ma=image.crop((i*15,0,(i+1)*15,24))
nubimgs.append(ma)
backpixels.append(image.getpixel((0,0)))
pixBlankEndPos.append(GetLastBlankPosition(ma))
print pixBlankEndPos
#对于每个数字图片的每个像素,如果对应位置非背景色,将该图片放到该位置的字典中,其结构如下,接下来用下面的数据统计来取得每个数字的特征像素
'''pixDir[pixel(x-x_offset,y),imgSeq]=picture<br>'''
for i in range(15):
for j in range(24):
ai=None
aj=None
pixDir[(i,j)]={}
for imgNum in range(nubimgs.__len__()):
if(nubimgs[imgNum].getpixel((i,j))!=backpixels[imgNum]):
pixDir[(i-pixBlankEndPos[imgNum],j)][imgNum]=nubimgs[imgNum]
"""nubimgs[0].putpixel ((i,j),nubimgs[imgNum].getpixel((i,j)))"""
'''下面将只有n个数字有的像素存到对应的文件夹中'''
for pix in pixDir.items():
if pix[1].__len__()<=6:
print pix
i=0
for pic in pix[1].items():
i+=1
if not os.path.exists(path+str(pix[1].__len__())):
os.mkdir(path+str(pix[1].__len__()))
pic[1].save(os.path.join(path+str(pix[1].__len__()),str(pix[0][0])+"_"+str(pix[0][1])+"__"+str(i)+".bmp"))

材料图片:

Python解析最简单的验证码Python解析最简单的验证码 Python解析最简单的验证码

解析结果如下

Python解析最简单的验证码

对应的文件夹中就放着n个图片共享的像素,接下来的分析我是手动分析的,其实也可以用程序写,不过要预先告诉程序哪个片段是什么数字,可以通过把图片名起为对应验证码来解析。因为这是后想到的,就没有实现了。

2.接下来就是使用得到的特征值来解析验证码

下面的方法用来取得背景色,方法同上面解析一样,沿图片最上面一层取颜色,因为最上面不绘制

def getBackColors(bmp):
list=[]
for i in range(60):
if bmp.getpixel((i,0)) not in list:
list.append(bmp.getpixel((i,0)))
return list

同上面解析一样,取得首绘偏移值

def GetLastBlankPosition(materialPic,x=0):
bc=getBackColors(materialPic)
for i in range(15):
for j in range(24):
if materialPic.getpixel((i+x,j)) not in bc:
return i

解析验证码,利用特征吗判断

def GetVaildJpgNumber(bmp):
print 'GetVaildJpgNumber'
vaildStr="";
backColors=getBackColors(bmp)<br>#对于一个验证码的4个数字分别验证,其x范围为n*15~(n+1)*15
for pos in range(4):<br>

#取得对应位置的首绘偏移值
offset=GetLastBlankPosition(bmp,pos*15)<br>

 #对于0-9,分别判断对应的特征是否为背景色,如果不是解析完成,是背景色则判断下一个数字,因为3的像素基本和其他图像共享,所以如果最后没有找到特定的数字,就是3
for nr in range(0,10):
isthisNr=True
for pix in NumberKeyPixel[nr]:
if pix[0]+offset>=15:
isthisNr=False
break
if bmp.getpixel((pix[0]+offset+pos*15,pix[1])) in backColors :
isthisNr=False
break;
if isthisNr and NumberKeyPixel[nr].__len__()!=0 :
vaildStr+=str(nr)
break
if vaildStr.__len__()==pos:
vaildStr+='3'
print vaildStr
return vaildStr

从网络抓取验证码,使用的是httplib,其中我们学校名我已替代为myschool

def GetVaildJpg ():
print 'GetVaildJpg'
headers={
'Accept': 'image/png, image/svg+xml, image/*;q=0.8, */*;q=0.5',
'Referer': 'http://zcc.myschool.edu.cn/',
'Accept-Language': 'zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko',
'Accept-Encoding': 'gzip, deflate',
'Host': 'zcc.myschool.edu.cn',
'DNT': '1',
'Connection': 'Keep-Alive',
'Cookie': sessionId
}
httpClient=httplib.HTTPConnection('zcc.myschool.edu.cn',80,timeout=300)
httpClient.request("GET",'http://zcc.myschool.edu.cn/image.jsp',None,headers)
response=httpClient.getresponse()
'''print response.getheaders()'''
stBmp=response.read()
bmp=Image.open(BytesIO(stBmp))
bmp.save('D:\PROJECT\PYTHON\catchDorm\catch.bmp')
'''bmp.show()'''
return GetVaildJpgNumber(bmp)

以上内容给大家介绍了Python解析最简单的验证码的相关知识,希望大家喜欢。

Python 相关文章推荐
使用Python的Scrapy框架编写web爬虫的简单示例
Apr 17 Python
python web框架学习笔记
May 03 Python
Python实现Logger打印功能的方法详解
Sep 01 Python
Python通过matplotlib绘制动画简单实例
Dec 13 Python
python绘制条形图方法代码详解
Dec 19 Python
Ubuntu16.04/树莓派Python3+opencv配置教程(分享)
Apr 02 Python
Python 判断文件或目录是否存在的实例代码
Jul 19 Python
详解使用python绘制混淆矩阵(confusion_matrix)
Jul 14 Python
python实现通过flask和前端进行数据收发
Aug 22 Python
20行Python代码实现视频字符化功能
Apr 13 Python
python plt可视化——打印特殊符号和制作图例代码
Apr 17 Python
Python内存泄漏和内存溢出的解决方案
Sep 26 Python
Python中http请求方法库汇总
Jan 06 #Python
python访问mysql数据库的实现方法(2则示例)
Jan 06 #Python
分享Python文本生成二维码实例
Jan 06 #Python
Python的MongoDB模块PyMongo操作方法集锦
Jan 05 #Python
使用Python神器对付12306变态验证码
Jan 05 #Python
Python聊天室实例程序分享
Jan 05 #Python
详解Python Socket网络编程
Jan 05 #Python
You might like
php.ini 配置文件的深入解析
2013/06/17 PHP
用jquery实现学校的校历(asp.net+jquery ui 1.72)
2010/01/01 Javascript
innerHTML与jquery里的html()区别介绍
2012/10/12 Javascript
JS批量操作CSS属性详细解析
2013/12/16 Javascript
JavaScript 基本概念
2015/01/20 Javascript
jquery实现简单的轮换出现效果实例
2015/07/23 Javascript
JS实现的网页背景闪电闪烁效果代码
2015/10/17 Javascript
跟我学习javascript的垃圾回收机制与内存管理
2015/11/23 Javascript
Angular.js中控制器之间的传值详解
2017/04/24 Javascript
d3.js实现立体柱图的方法详解
2017/04/28 Javascript
详解vue的diff算法原理
2018/05/20 Javascript
node.js中TCP Socket多进程间的消息推送示例详解
2018/07/10 Javascript
详解微信小程序实现仿微信聊天界面(各种细节处理)
2019/02/17 Javascript
手把手教你使用TypeScript开发Node.js应用
2019/05/06 Javascript
Angular2实现的秒表及改良版示例
2019/05/10 Javascript
vue将文件/图片批量打包下载zip的教程
2020/10/21 Javascript
Python高效编程技巧
2013/01/07 Python
Python实现的ini文件操作类分享
2014/11/20 Python
python正则分析nginx的访问日志
2017/01/17 Python
django轻松使用富文本编辑器CKEditor的方法
2017/03/30 Python
Python二叉树的定义及常用遍历算法分析
2017/11/24 Python
基于Python log 的正确打开方式
2018/04/28 Python
详解django自定义中间件处理
2018/11/21 Python
理想高通滤波实现Python opencv示例
2019/01/30 Python
python numpy库linspace相同间隔采样的实现
2020/02/25 Python
Python openpyxl 插入折线图实例
2020/04/17 Python
Python计算信息熵实例
2020/06/18 Python
python 5个顶级异步框架推荐
2020/09/09 Python
CSS中越界问题的经典解决方案【推荐】
2016/04/19 HTML / CSS
简单几步用纯CSS3实现3D翻转效果
2019/01/17 HTML / CSS
Reformation官网:美国女装品牌
2018/09/14 全球购物
高中综合实践活动总结
2014/07/07 职场文书
个人委托书怎么写
2014/09/17 职场文书
六查六看六改心得体会
2014/10/14 职场文书
预备党员个人总结
2015/02/14 职场文书
医务人员岗前培训心得体会
2016/01/08 职场文书