文档章节

Python生成图片验证码

翼动动空
 翼动动空
发布于 2016/05/13 15:44
字数 910
阅读 910
收藏 8
点赞 2
评论 0
最近公司网站,需要在注册模块添加验证码,防止其他人频繁的恶意注册,我们后端使用的是python进行开发,所以研究了下python图片验证码的方法。

最后确定使用python里面PIL库,通过Image, ImageDraw, ImageFont, ImageFilter的模块生成图片验证码

设计思路(这里就不画图了):
(1)用户填写用户名(必须先填)
(2)客户端点击获取验证码,请求里带用户名参数
(3)调用生成验证码接口
(4)按一定规则将用户名生成键值,以生成的键值为键,验证码为值,保存到缓存中
(5)将验证码的字节流返回客户端并显示
(6)输入验证码,点击注册
(7)后台根据用户名和验证码验证

生成验证码函数
#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter

try:
    import cStringIO as StringIO
except ImportError:
    import StringIO

_letter_cases = "abcdefghjkmnpqrstuvwxy"                        # 小写字母
_upper_cases = "ABCDEFGHJKLMNPQRSTUVWXY"                        # 大写字母
_numbers = "1234567890"                                         # 数字
init_chars = ''.join((_letter_cases, _upper_cases, _numbers))   # 生成允许的字符集合
default_font = "./DejaVuSans.ttf"                               # 验证码字体


# 生成验证码接口
def generate_verify_image(size=(120, 30),
                          chars=init_chars,
                          img_type="GIF",
                          mode="RGB",
                          bg_color=(255, 255, 255),
                          fg_color=(0, 0, 255),
                          font_size=18,
                          font_type=default_font,
                          length=4,
                          draw_lines=True,
                          n_line=(1, 2),
                          draw_points=True,
                          point_chance=2,
                          save_img=False):

    """
    生成验证码图片
    :param size: 图片的大小,格式(宽,高),默认为(120, 30)
    :param chars: 允许的字符集合,格式字符串
    :param img_type: 图片保存的格式,默认为GIF,可选的为GIF,JPEG,TIFF,PNG
    :param mode: 图片模式,默认为RGB
    :param bg_color: 背景颜色,默认为白色
    :param fg_color: 前景色,验证码字符颜色,默认为蓝色#0000FF
    :param font_size: 验证码字体大小
    :param font_type: 验证码字体,默认为 DejaVuSans.ttf
    :param length: 验证码字符个数
    :param draw_lines: 是否划干扰线
    :param n_line: 干扰线的条数范围,格式元组,默认为(1, 2),只有draw_lines为True时有效
    :param draw_points: 是否画干扰点
    :param point_chance: 干扰点出现的概率,大小范围[0, 100]
    :param save_img: 是否保存为图片
    :return: [0]: 验证码字节流, [1]: 验证码图片中的字符串
    """

    width, height = size  # 宽, 高
    img = Image.new(mode, size, bg_color)  # 创建图形
    draw = ImageDraw.Draw(img)  # 创建画笔

    def get_chars():
        """生成给定长度的字符串,返回列表格式"""

        return random.sample(chars, length)

    def create_lines():
        """绘制干扰线"""

        line_num = random.randint(*n_line)  # 干扰线条数

        for i in range(line_num):
            # 起始点
            begin = (random.randint(0, size[0]), random.randint(0, size[1]))
            # 结束点
            end = (random.randint(0, size[0]), random.randint(0, size[1]))
            draw.line([begin, end], fill=(0, 0, 0))

    def create_points():
        """绘制干扰点"""

        chance = min(100, max(0, int(point_chance)))  # 大小限制在[0, 100]

        for w in xrange(width):
            for h in xrange(height):
                tmp = random.randint(0, 100)
                if tmp > 100 - chance:
                    draw.point((w, h), fill=(0, 0, 0))

    def create_strs():
        """绘制验证码字符"""

        c_chars = get_chars()
        strs = ' %s ' % ' '.join(c_chars)  # 每个字符前后以空格隔开

        font = ImageFont.truetype(font_type, font_size)
        font_width, font_height = font.getsize(strs)

        draw.text(((width - font_width) / 3, (height - font_height) / 3),
                  strs, font=font, fill=fg_color)

        return ''.join(c_chars)

    if draw_lines:
        create_lines()
    if draw_points:
        create_points()
    strs = create_strs()

    # 图形扭曲参数
    params = [1 - float(random.randint(1, 2)) / 100,
              0,
              0,
              0,
              1 - float(random.randint(1, 10)) / 100,
              float(random.randint(1, 2)) / 500,
              0.001,
              float(random.randint(1, 2)) / 500
              ]
    img = img.transform(size, Image.PERSPECTIVE, params)  # 创建扭曲

    img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)  # 滤镜,边界加强(阈值更大)

    mstream = StringIO.StringIO()
    img.save(mstream, img_type)

    if save_img:
        img.save("validate.gif", img_type)

    return mstream, strs


if __name__ == "__main__":
    mstream, strs = generate_verify_image(save_img=True)
    print strs
注意:返回的流要进行转换,在返回前端
self.write(simplejson.dumps({'code': 0, 'img': stream.getvalue().encode('base64')}))
这里是将stream的值进行了一次base64的编码

前端js设置图片src代码
$("#verify_code_img").attr("src", "data:image/gif;base64," + data.img);

 

效果

是不是很简单,下次分享前端生成图片验证码的方法

© 著作权归作者所有

共有 人打赏支持
翼动动空
粉丝 15
博文 69
码字总数 36207
作品 0
成都
程序员
使用python PIL库实现简单验证码的去噪

首先要感谢一下字符型图片验证码识别完整过程及Python实现的博主,我的大部分知识点都是从他那里学来的。 想要识别验证码,收集足够多的样本后,首先要做的就是对验证码原始图片进行处理,对...

u012067766 ⋅ 04/20 ⋅ 0

JAVA使用字节流将本地图片传到前端

JAVA使用字节流将本地图片传到前端 01.基本介绍 在我们日常的开发中,会遇到对验证码的使用问题(验证码的作用这里不多多说,避免程序被恶意攻击等),如何是的前端和后端保持一致是一个问题...

meiqi0538 ⋅ 04/09 ⋅ 0

【Python搞搞轻量博客】必要的知识

大家好,我又回来啦! 今天准备下数据库的,但是我想了想,那玩意讲的东西太多,怕大家一下接受不了,所以数据库那玩意我需要分几篇写,毕竟是重点嘛。 So ~ 我来说说今天我要讲的东西: 更多...

仙宇 ⋅ 05/09 ⋅ 0

Python3.6实现12306火车票自动抢票,附源码

Python(发音:英[?pa?θ?n],美[?pa?θɑ:n]),是一种面向对象、直译式电脑编程语言,也是一种功能强大的通用型语言,已经具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理...

猫咪编程 ⋅ 06/05 ⋅ 0

python3,Django验证码生成方法

python3,Django验证码生成方法 一号门-程序员的工作,程序员的生活(java,python,delphi实战)2017-09-0331 阅读 生成方法验证码python3Django 记得很久以前有尝试过python2.7, Django生成验证码...

一号门-程序员的工作,程序员的生活(java,python,delphi实战) ⋅ 2017/09/03 ⋅ 0

一行python命令, 生成网站二维码

将网址生成二维码是一个古老而常用的需求, 这里我们用python的库, 一键生成二维码图片 第一步: 安装 第二步: 生成网址二维码 命令行图形 生成的图片 qrcode是完全开源的小工具, 开源地址 ht...

木子昭 ⋅ 06/16 ⋅ 0

Python 3.7 将引入 dataclass 装饰器

简评:Python 3.7 将于今年夏天发布,Python 3.7 中将会有许多新东西,最激动人心的新功能之一是 dataclass 装饰器。 什么是 Data Class 大多数 Python 开发人员编写过很多像下面这样的类: ...

极光推送 ⋅ 05/03 ⋅ 0

Python 数据挖掘学习 一 结巴分词

近期,想对古典小说进行索引,和知识挖掘,所以研究了下python数据挖掘方面的知识 Python安装 python学习 一 python语法,及变量类型 python学习 二 爬一个图片网站上 python学习 二 02 爬一...

shuilan0066 ⋅ 01/22 ⋅ 0

两把王者荣耀的时间学会Python图片打码技能——「实验一小时」今晚开启!

关注「实验楼」,每天分享一个项目教程 「 实验一小时 」今晚开启,实验楼技术天团带你一小时做一个项目。 今晚 7:30 ,曾任职于腾讯、盛大等一线互联网公司的天火老师,将在B站带来免费直播...

moy37rqw1jarn33bgzk ⋅ 04/18 ⋅ 0

福利 | Python专场竞技,这些书给你加把力!

端午节将至,各地龙舟备战竞技,粽子部队也整装待发。小编掐指一算,这种热闹的时节,是时候展现真正的技(fu)术(li)了! (“Python号”龙舟闪亮登场!) Python作为当下最流行的编程语言...

⋅ 06/15 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

vbs 取文件大小 字节

dim namedim fs, s'name = Inputbox("姓名")'msgbox(name)set fs = wscript.createobject("scripting.filesystemobject") 'fs为FSO实例if (fs.folderexists("c:\temp"))......

vga ⋅ 14分钟前 ⋅ 1

高并发之Nginx的限流

首先Nginx的版本号有要求,最低为1.11.5 如果低于这个版本,在Nginx的配置中 upstream web_app { server 到达Ip1:端口 max_conns=10; server 到达Ip2:端口 max_conns=10; } server { listen ...

算法之名 ⋅ 今天 ⋅ 0

Spring | IOC AOP 注解 简单使用

写在前面的话 很久没更新笔记了,有人会抱怨:小冯啊,你是不是在偷懒啊,没有学习了。老哥,真的冤枉:我觉得我自己很菜,还在努力学习呢,正在学习Vue.js做管理系统呢。即便这样,我还是不...

Wenyi_Feng ⋅ 今天 ⋅ 0

博客迁移到 https://www.jianshu.com/u/aa501451a235

博客迁移到 https://www.jianshu.com/u/aa501451a235 本博客不再更新

为为02 ⋅ 今天 ⋅ 0

win10怎么彻底关闭自动更新

win10自带的更新每天都很多,每一次下载都要占用大量网络,而且安装要等得时间也蛮久的。 工具/原料 Win10 方法/步骤 单击左下角开始菜单点击设置图标进入设置界面 在设置窗口中输入“服务”...

阿K1225 ⋅ 今天 ⋅ 0

Elasticsearch 6.3.0 SQL功能使用案例分享

The best elasticsearch highlevel java rest api-----bboss Elasticsearch 6.3.0 官方新推出的SQL检索插件非常不错,本文一个实际案例来介绍其使用方法。 1.代码中的sql检索 @Testpu...

bboss ⋅ 今天 ⋅ 0

informix数据库在linux中的安装以及用java/c/c++访问

一、安装前准备 安装JDK(略) 到IBM官网上下载informix软件:iif.12.10.FC9DE.linux-x86_64.tar放在某个大家都可以访问的目录比如:/mypkg,并解压到该目录下。 我也放到了百度云和天翼云上...

wangxuwei ⋅ 今天 ⋅ 0

PHP语言系统ZBLOG或许无法重现月光博客的闪耀历史[图]

最近在写博客,希望通过自己努力打造一个优秀的教育类主题博客,名动江湖,但是问题来了,现在写博客还有前途吗?面对强大的自媒体站点围剿,还有信心和可能型吗? 至于程序部分,我选择了P...

原创小博客 ⋅ 今天 ⋅ 0

IntelliJ IDEA 2018.1新特性

工欲善其事必先利其器,如果有一款IDE可以让你更高效地专注于开发以及源码阅读,为什么不试一试? 本文转载自:netty技术内幕 3月27日,jetbrains正式发布期待已久的IntelliJ IDEA 2018.1,再...

Romane ⋅ 今天 ⋅ 0

浅谈设计模式之工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻...

佛系程序猿灬 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部