Flask实战第40天:图片验证码生成技术
图片验证码生成
安装pillow
pip install pillow
在utils下新建python package命名为captcha
把需要需要用到的字体放在captcha下
编辑captcha.__init__.py, 生成验证码
import random
import string
# Image:一个画布
# ImageDraw:一个画笔
# ImageFont:画笔的字体 # pip install pillow
from PIL import Image, ImageDraw, ImageFont class Captcha(object):
# 生成几位数的验证码
number = 4
# 验证码图片的高度和宽度
size = (100, 30)
# 验证码字体大小
fontsize = 25
#加入干扰线条数
line_number = 2 #构建一个验证码源文本
SOURCE = list(string.ascii_letters)
for index in range(0, 10):
SOURCE.append(str(index)) #用来绘制干扰线
@classmethod
def __gene_line(cls, draw, width, height):
begin = (random.randint(0, width), random.randint(0, height))
end = (random.randint(0, width), random.randint(0, height))
draw.line([begin, end], fill=cls.__gene_random_color(), width=2) # 用来绘制干扰点
@classmethod
def __gene_points(cls, draw, point_chance, width, height):
chance = min(100, max(0, int(point_chance))) #大小限制在[0, 100]
for w in range(width):
for h in range(height):
tmp = random.randint(0, 100)
if tmp > 100 - chance:
draw.point((w, h), fill=cls.__gene_random_color()) # 生成随机的颜色
@classmethod
def __gene_random_color(cls, start=0, end=255):
random.seed()
return (random.randint(start, end),random.randint(start, end), random.randint(start, end)) # 随机选择一个字体
@classmethod
def __gene_random_font(cls):
fonts = [
'Courgette-Regular.ttf',
'LHANDW.TTF',
'Lobster-Regular.ttf',
'verdana.ttf'
]
font = random.choice(fonts)
return 'utils/captcha/' + font # 用来随机生成一个字符串
@classmethod
def gene_text(cls, number):
#num是生成验证码的位数
return ''.join(random.sample(cls.SOURCE, number)) # 生成验证码
@classmethod
def gene_graph_captcha(cls):
#验证码图片的高和宽
width, height = cls.size
#创建图片
image = Image.new('RGBA', (width,height),cls.__gene_random_color(0, 100))
#验证码的字体
font = ImageFont.truetype(cls.__gene_random_font(), cls.fontsize)
#创建画笔
draw = ImageDraw.Draw(image)
#生成字符串
text = cls.gene_text(cls.number)
#获取字体尺寸
font_width, font_height = font.getsize(text)
#填充字符串
draw.text(((width - font_width) / 2, (height - font_height) / 2), text, font=font,
fill=cls.__gene_random_color(150, 255))
#绘制干扰线
for x in range(0, cls.line_number):
cls.__gene_line(draw, width, height)
#绘制噪点
cls.__gene_points(draw, 10, width, height)
return (text, image)
captcha.__init__.py
测试的时候我发现有些字体会导致程序崩溃,所以,我只设置了一个字体 fonts = ['verdana.ttf']
编辑视图。我们把它放到 公共的common里面去,编辑common.views.py
from flask import Blueprint, make_response
from utils.captcha import Captcha
from io import BytesIO bp = Blueprint('common', __name__, url_prefix='/c') #common太长,改为c @bp.route('/')
def index():
return 'common index' @bp.route('/graph_captcha/')
def graph_captcha():
text, image = Captcha.gene_graph_captcha()
out = BytesIO()
image.save(out, 'png')
out.seek(0)
resp = make_response(out.read())
resp.content_type = 'image/png'
return resp
访问http://127.0.0.1:5000/c/graph_captcha/
图片验证放到注册页面。点击一次更换一张
图片验证码放在注册页面比较简单,只需要把编辑front_signup.html,把里面的“图片验证码”字换成img标签,src设置成图片验证码的url
<div class="input-group">
<input type="text" class="form-control" name="graph_captcha" placeholder="图形验证码">
<span class="input-group-addon captcha-addon"> <!--加了一个类captcha-addon-->
<img id="captcha-img" src="{{ url_for('common.graph_captcha') }}"><!--加了id aptcha-img-->
</span>
</div> <!--样式-->
.captcha-addon{
padding: 0; //这是内边距为0,因为input-group-addon有设置内边距
overflow: hidden; //当里面的元素超出则隐藏
} #captcha-img{
height: 32px; //设置图片的高度为32px
cursor: pointer; //当鼠标移到图片上变成手的图标
}
还有个需求就是,我们点击一个图片验证码,则需要更换成另外一个。
图片验证码更换,只需要替换它的url就可以,但是它的url就是一个http://127.0.0.1:5000/common/captcha/
所以只需要请求的时候加个参数http://127.0.0.1:5000/front/captcha/?xxx=<随机数>即可
我还需要对?xxx=<随机数>做处理,不然当用户点击多次,?xxx=<随机数>&xxx=<随机数>...变得很长,而我们只需要一个就可以了,这里封装了一个js, 存放在static/common/js/bbsparams.js中
/**
* Created by Administrator on 2017/3/24.
*/ var bbsparam = {
setParam: function (href,key,value) {
// 重新加载整个页面
var isReplaced = false;
var urlArray = href.split('?');
if(urlArray.length > 1){
var queryArray = urlArray[1].split('&');
for(var i=0; i < queryArray.length; i++){
var paramsArray = queryArray[i].split('=');
if(paramsArray[0] == key){
paramsArray[1] = value;
queryArray[i] = paramsArray.join('=');
isReplaced = true;
break;
}
} if(!isReplaced){
var params = {};
params[key] = value;
if(urlArray.length > 1){
href = href + '&' + $.param(params);
}else{
href = href + '?' + $.param(params);
}
}else{
var params = queryArray.join('&');
urlArray[1] = params;
href = urlArray.join('?');
}
}else{
var param = {};
param[key] = value;
if(urlArray.length > 1){
href = href + '&' + $.param(param);
}else{
href = href + '?' + $.param(param);
}
}
return href;
}
};
bbsparams
然后在static/front/js/下新建front_signup.js,当点击图片时更换src
$(function(){
$('#captcha-img').click(function (event) {
var self = $(this);
var src = self.attr('src');
var newsrc = bbsparam.setParam(src,'xx',Math.random());
self.attr('src',newsrc);
});
});
在signup.html中引入上面两个js
<script src="{{ url_for('static', filename='common/js/bbsparam.js') }}"></script>
<script src="{{ url_for('static', filename='front/js/front_signup.js') }}"></script>
Flask实战第40天:图片验证码生成技术的更多相关文章
- JavaWeb开发之普通图片验证码生成技术与算术表达式验证码生成技术
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6134649.html 另:算术验证码生成的JSP.Servlet实现均已移植github:https:/ ...
- Atitit 图片 验证码生成attilax总结
Atitit 图片 验证码生成attilax总结 1.1. 图片验证码总结1 1.2. 镂空文字 打散 干扰线 文字扭曲 粘连2 1.1. 图片验证码总结 因此,CAPTCHA在图片验证码这一应用点 ...
- 开发工具类API调用的代码示例合集:六位图片验证码生成、四位图片验证码生成、简单验证码识别等
以下示例代码适用于 www.apishop.net 网站下的API,使用本文提及的接口调用代码示例前,您需要先申请相应的API服务. 六位图片验证码生成:包括纯数字.小写字母.大写字母.大小写混合.数 ...
- [转]php 图片验证码生成 前后台验证
本文转自:https://www.cnblogs.com/xiaoyezi/p/3541195.html 自己从前一段时间做了个php小项目,关于生成图片验证码生成和后台的验证,把自己用到的东西总结一 ...
- php 图片验证码生成 前后台验证
自己从前一段时间做了个php小项目,关于生成图片验证码生成和后台的验证,把自己用到的东西总结一下,希望大家在用到相关问题的时候可以有一定的参考性. 首先,php验证码生成. 代码如下: 1.生成图像代 ...
- 一篇Java图片验证码生成的代码
package projectUtil; /** * @author tian * @date 2019/4/1015:58 */ import javax.imageio.ImageIO; impo ...
- Java图片验证码生成工具
直接把以下代码拷贝使用: import javax.imageio.ImageIO;import java.awt.*;import java.awt.image.BufferedImage;impo ...
- .net图片验证码生成、点击刷新及验证输入是否正确
①创建ValidateCode.aspx,在ValidateCode.aspx.cs中加入如下代码.生成验证码图片,在页面上输出,输出jpeg格式. protected void Page_Load( ...
- node 图片验证码生成
var captchapng = require('captchapng'); var http = require("http") var server = http.creat ...
随机推荐
- cookie与session的区别与应用
通常我们所说的浏览器自动保存密码,下次不用登陆,提示一次就不再出现的内容,大部分通过cookie或者session来实现的. cookie的概念 cookie是浏览器(User Agent)访问一些网 ...
- iOS通知传值
NSMutableDictionary *params = [NSMutableDictionary dictionary]; params[@"loginName"] = @&q ...
- bzoj 4378: [POI2015]Logistyka ——树桩数组+离散化
Description 维护一个长度为n的序列,一开始都是0,支持以下两种操作:1.U k a 将序列中第k个数修改为a.2.Z c s 在这个序列上,每次选出c个正数,并将它们都减去1,询问能否进行 ...
- 25、如何实现redis集群?
由于Redis出众的性能,其在众多的移动互联网企业中得到广泛的应用.Redis在3.0版本前只支持单实例模式,虽然现在的服务器内存可以到100GB.200GB的规模,但是单实例模式限制了Redis没法 ...
- python中multiprocessing模块
multiprocess模块那来干嘛的? 答:利用multiprocessing可以在主进程中创建子进程.Threading是多线程,multiprocessing是多进程. #该模块和Threadi ...
- python开发第二十六天CMDB
概要: 1.采集资产 2.API 一.资产采集 1.采集方式的配置 2.插件的定制 3.测试模式 4.错误日志(必须是行级的详细错误信息) 5.汇报数据-->遵循资产的唯一性 (1)只针对物理机 ...
- linux编程之共享内存
linux 进程间通信(IPC)包括3种机制:消息队列.信号量.共享内存.消息队列和信号量均是内核空间的系统对象,经由它们 的数据需要在内核和用户空间进行额外的数据拷贝:而共享内存和访问它的所有应用程 ...
- C C++ 常被人问的问题分析
正文 - 开始了, 直接扯淡 以下都是自己面试中遇到的常见的问题.如有不妥的地方就当见笑了. 哈哈 1. 谈谈你们服务器的架构吧. 分析: 假如这是第一个问题, 你可以走了. 可能各方面原因他不想 ...
- ASPxCheckBoxList控件获取selected项的text和value的方法
设ASPxCheckBoxList的ClientInstanceName为list_ var needtext; for (var i = 0; i < list_.GetSelectedIte ...
- JQuery一个对象绑定多个事件
jQuery("#id").click(func1).mouseover(func2)//方法连写,func为方法的名字 jQuery("#id").click ...