这篇文章上次修改于 3386 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
最近闲来无事,研究了一下python破解验证码
参考地址:http://vipscu.blog.163.com/blog/static/18180837220134234528457/
具体思路如下:
1、采样,采集目标网站的验证码样本
2、将采集的样本验证码进行二进值转化,也即是背景变白,验证码文字变黑
3、分割转化好的验证码,挑选好的作为模
4、将要破解的验证码与库里面的模对比
直接上代码:
1、采样,采集目标网站的验证码样本
#encoding:utf-8
import urllib
#验证码地址
url="http://www.njjg.gov.cn:81/GetValidate.aspx"
for i in range(50):
print "download", i
file("./code/%04d.jpg" % i, "wb").write(urllib.urlopen(url).read())
2、二进值转化
#encoding:utf-8
#二值化处理下载的图片
import os
from PIL import Image
j=1
dir='./code/'
path='./font/'
for f in os.listdir(dir):
if f.endswith('.jpg'):
img=Image.open(dir+f) #读取图片
img=img.convert('RGBA')
pixdata = img.load()
#二值化处理 即验证码变成黑色,背景变成白色
for y in xrange(img.size[1]): #img.size[1] 图片高度
for x in xrange(img.size[0]): #img.size[0] 图片宽度
if pixdata[x,y][0] == 192:
pixdata[x,y]=(255,255,255,255)
for y in xrange(img.size[1]): #img.size[1]图片高度
for x in xrange(img.size[0]): #img.size[0]图片宽度
if pixdata[x,y][0] < 90:
pixdata[x,y]=(0,0,0,255)
for y in xrange(img.size[1]): #img.size[1] 图片高度
for x in xrange(img.size[0]): #img.size[0] 图片宽度
if pixdata[x,y][1] < 255:
pixdata[x,y]=(0,0,0,255)
img.save(path+f,"jpeg")
3、制作库模
import os,Image
j=1
dir='./font/'
for f in os.listdir(dir):
if f.endswith(".jpg"):
img=Image.open(dir+f)
for i in range(4):
x=3+i*18 #这里的3和18是根据具体的验证码算出来的
y=4 #4是根据具体的验证码算出来的 可以用ps打开,放大图片来数出像素
img.crop((x,y,x+13,y+14)).save("./font/mode/%d.jpg" % j)
print "j=",j
j += 1
4、准备工作做完,编写主程序代码
#encoding:utf-8
import os
from PIL import Image
#转化二进值
def binary(f):
img = Image.open(f)
img = img.convert('RGBA')
pixdata = img.load()
for y in xrange(img.size[1]): #img.size[1] 图片高度
for x in xrange(img.size[0]): #img.size[0] 图片宽度
if pixdata[x,y][0] == 192:
pixdata[x,y]=(255,255,255,255)
for y in xrange(img.size[1]): #img.size[1]图片高度
for x in xrange(img.size[0]): #img.size[0]图片宽度
if pixdata[x,y][0] < 90:
pixdata[x,y]=(0,0,0,255)
for y in xrange(img.size[1]): #img.size[1] 图片高度
for x in xrange(img.size[0]): #img.size[0] 图片宽度
if pixdata[x,y][1] < 255:
pixdata[x,y]=(0,0,0,255)
return img
#图形分割
nume = 0
def division(img):
global nume
font=[]
for i in range(4):
x=3+i*18
y=4
temp=img.crop((x,y,x+13,y+14))
temp.save("./tmp/%d.jpg" % nume)
nume=nume+1
font.append(temp)
return font
#取出对应的值
def recognize(img):
fontMods = []
modelist = [1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
for i in modelist:
file="./mode/%s.jpg" % i
if os.path.isfile(file):
fontMods.append((str(i), Image.open("./mode/%s.jpg" % i)))
result=""
font=division(img)
for i in font:
target=i
points = []
for mod in fontMods:
diffs = 0
for yi in range(14):
for xi in range(13):
if 0 in target.getpixel((xi,yi)):
compare=0
else:
compare=255
if 0 in mod[1].getpixel((xi, yi)):
tcv=0
else:
tcv=255
if tcv != compare:
diffs += 1
points.append((diffs,mod[0]))
points.sort()
print points
result += points[0][1]
return result
if __name__ == '__main__':
imgfile="./code/0041.jpg"
img=binary(imgfile)
rs=recognize(img)
print rs
小结:
次方法的关键在于制作库模,库模做的准确则破解成功率就高
没有评论