Python解析最简单的验证码

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

材料图片:

 

解析结果如下

对应的文件夹中就放着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解析最简单的验证码的相关知识,希望大家喜欢。

(0)

相关推荐

  • Python随机生成一个6位的验证码代码分享

    1. 生成源码 复制代码 代码如下: # -*- coding: utf-8 -*- import random def generate_verification_code():     ''' 随机生成6位的验证码 '''     code_list = []     for i in range(10): # 0-9数字         code_list.append(str(i))     for i in range(65, 91): # A-Z         code_list.

  • python 图片验证码代码

    下面是一个实战项目的结果. 复制代码 代码如下: #coding: utf-8 import Image,ImageDraw,ImageFont,os,string,random,ImageFilter def initChars(): """ 允许的字符集合,初始集合为数字.大小写字母 usage: initChars() param: None return: list 返回允许的字符集和 for: picChecker类初始字符集合 todo: Nothing &quo

  • Python 随机生成中文验证码的实例代码

    python代码 复制代码 代码如下: # -*- coding: utf-8 -*- import Image,ImageDraw,ImageFont import random import math, string class RandomChar(): """用于随机生成汉字""" @staticmethod def Unicode(): val = random.randint(0x4E00, 0x9FBF) return unichr

  • Python生成验证码实例

    本文实例展示了Python生成验证码的方法,具有很好的实用价值.分享给大家供大家参考.具体实现方法如下: 前台页面代码如下: <div> <img id="authcode_img" alt="验证码" src="/registration/makeimage/{{time}}"/> <!-- time 任意随机数(时间戳),防止页面缓存 导致验证码不能更新--> <a href="javasc

  • python使用pil生成图片验证码的方法

    本文实例讲述了python使用pil生成图片验证码的方法.分享给大家供大家参考.具体实现方法如下: # -*- coding: utf-8 -*- #导入三个模块 import Image,ImageDraw,ImageFont import random import math '''基本功能''' #图片宽度 width = 100 #图片高度 height = 40 #背景颜色 bgcolor = (255,255,255) #生成背景图片 image = Image.new('RGB',

  • python为tornado添加recaptcha验证码功能

    复制代码 代码如下: from urllib.request import urlopen    from urllib.parse import urlencode    import tornado.httpserver    import tornado.ioloop    import tornado.web #获取key: https://www.google.com/recaptcha/whyrecaptcha    publickey = '填入你的 public key'   

  • python实现带验证码网站的自动登陆实现代码

    早听说用python做网络爬虫非常方便,正好这几天单位也有这样的需求,需要登陆XX网站下载部分文档,于是自己亲身试验了一番,效果还不错. 本例所登录的某网站需要提供用户名,密码和验证码,在此使用了python的urllib2直接登录网站并处理网站的Cookie. Cookie的工作原理: Cookie由服务端生成,然后发送给浏览器,浏览器会将Cookie保存在某个目录下的文本文件中.在下次请求同一网站时,会发送该Cookie给服务器,这样服务器就知道该用户是否合法以及是否需要重新登录. Pyth

  • python生成随机验证码(中文验证码)示例

    复制代码 代码如下: # -*- coding: utf-8 -*-import Image,ImageDraw,ImageFontimport randomimport math, string class RandomChar():  """用于随机生成汉字"""  @staticmethod  def Unicode():    val = random.randint(0x4E00, 0x9FBF)    return unichr(va

  • python 图片验证码代码分享

    复制代码 代码如下: #coding: utf-8 import Image,ImageDraw,ImageFont,os,string,random,ImageFilter def initChars(): """ 允许的字符集合,初始集合为数字.大小写字母 usage: initChars() param: None return: list 返回允许的字符集和 for: picChecker类初始字符集合 todo: Nothing """

  • Python解析最简单的验证码

    最近在学python,正好遇到学校需要选宿舍,就用python写了一个抢宿舍的软件.其中有一个模块是用来登陆的,登陆的时候需要输入验证码,不过后来发现了直接可以绕过验证码直接登陆的bug.不过这是另外的话题,开始的时候我并没有发现这个隐藏起来的秘密,所以我就写了这个python代码段用来实现解析验证码的功能. 我们学校的验证码是最简单的验证码,形式大概如下: 其中这个图片的大小是60X24像素的,大概每个数字的大小是15X24像素. 观察这个验证码之后可以发现,验证码中只有数字而且数字的字体很规

  • Python实现一个简单的验证码程序

    老师讲完random函数,自己写的,虽然和老师示例的不那么美观,智能,但是也自己想出来的,所以记录一下,代码就需要自己不断的自己练习,实战,才能提高啊!不然就像我们这些大部分靠自学的人,何时能学会.还有就是,这次听老师的,把自己的代码添加注释,所以这次把很简单的代码都写上了注释,而且很大白话,不管有没有接触过python的,我相信仔细看了,肯定能看懂.如果看完,再自己尝试着默写出来,那就是更好到了,好了进入正题: 自己写的: __Author__ = "Zhang Peng" impo

  • 用python实现一个简单的验证码

    我们经常在登录一个网站,或者注册的时候需要输入一个验证码,有时候觉得很烦,因为有些验证码不仅复杂还看不清,许多用户就会因为这些而懒得再登录或者注册之类的. 既然验证码会造成流失用户的风险,为什么大家都还要使用验证码呢? 这是验证码在一定程度上起到保护网站安全的作用,比如防止大规模恶意注册(比如手机验证码形式,一机一户),再比如反爬虫(至少不会轻易让你爬取数据)等,你看用户基数最大的12306,就会有各种验证码. 既然验证码这么重要,它的原理是什么?是怎么实现的? 它的原理其实很简单,就是在服务器

  • Python + Flask 实现简单的验证码系统

    一.写在前面 现在无论大大小小的网站,基本上都会使用验证码,登录的时候要验证,下载的时候要验证,而使用的验证码也从那些简简单单的字符图形验证码"进化"成了需要进行图文识别的验证码.需要拖动滑块的滑动验证码.甚至还有手机验证码.当你与之打交道的时候,有没有考虑过其背后的原理呢?当然了,对于那些复杂的验证码我们想要弄得一清二楚还是很难的,但是可以挑软柿子捏嘛--字符图形验证码,就这样,我决定用 Python + Flask 制作出一个简单的验证码系统来,话不多说,撸起袖子加油干! 二.基本

  • python解析xml简单示例

    本文实例讲述了python解析xml的方法.分享给大家供大家参考,具体如下: xml是除了json之外另外一个比较常用的用来做为数据交换的载体格式.对于一些比较固定的数据,直接保存在xml中,还可以免去去数据库中查询的麻烦.而且直接读小文件,性能比查询数据库应该更好,下面一个例子,如何用python解析xml数据,xml数据是省份,城市 数据,内容如下: <?xml version="1.0" encoding="utf-8" ?> <countr

  • Python random模块用法解析及简单示例

    用法示例: import random # 1)随机小数 print(random.random()) # 获取大于0且小于1 之间的小数 random.random() print(random.uniform(1, 4)) # 获取大于1小于3的小数 # 2)随机整数 print(random.randint(1, 9)) # 获取大于等于1且小于等于9之间的整数 print(random.randrange(1, 9)) # 获取大于等于1且小于9之间的整数 print(random.ra

  • Python实现简单生成验证码功能【基于random模块】

    本文实例讲述了Python实现简单生成验证码功能.分享给大家供大家参考,具体如下: 验证码一般用来验证登陆.交易等行为,减少对端为机器操作的概率,python中可以使用random模块,char()内置函数来实现一个简单的验证码功能. import random def veri_code(): li = [] for i in range(6): #循环6次,生成6个字符 r = random.randrange(0, 5) #随机生成0-4之间的数字 if r == 1 or r == 4:

  • Python文本处理简单易懂方法解析

    这篇文章主要介绍了Python文本处理简单易懂方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 自从认识了python这门语言,所有的事情好像变得容易了,作为小白,逗汁儿今天就为大家总结一下python的文本处理的一些小方法. 话不多说,代码撸起来. python大小写字符互换 在进行大小写互换时,常用到的方法有4种,upper().lower().capitalize() 和title(). str = "www.dataCASTLE.

  • Python 解析简单的XML数据

    问题 你想从一个简单的XML文档中提取数据. 解决方案 可以使用 xml.etree.ElementTree 模块从简单的XML文档中提取数据.为了演示,假设你想解析Planet Python上的RSS源.下面是相应的代码: from urllib.request import urlopen from xml.etree.ElementTree import parse # Download the RSS feed and parse it u = urlopen('http://plane

  • Python实现一个简单三层神经网络的搭建及测试 代码解析

    目录 1.初始化 2.预测 3.训练 4.测试 废话不多说了,直接步入正题,一个完整的神经网络一般由三层构成:输入层,隐藏层(可以有多层)和输出层.本文所构建的神经网络隐藏层只有一层.一个神经网络主要由三部分构成(代码结构上):初始化,训练,和预测.首先我们先来初始化这个神经网络吧! 1.初始化 我们所要初始化的内容包括:神经网络每层上的神经元个数(这个是根据实际问题输入输出而得到的,我们将它设置为一个可自定义量). 不同层间数据互相传送的权重值. 激活函数(模拟自然界的神经元,刺激信号需要达到

随机推荐