`
liaofeng_xiao
  • 浏览: 126093 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

pycaptcha

 
阅读更多
pycaptcha是python的开源图片验证码库,很基础,但也记录一下吧。

1. 目录结构
下载pycaptcha,基本目录结构如下:
.
| -- Base.py: 定义BaseCaptcha,提供Factory接口供外面生成、验证验证码
| -- data: 用来存放数据的目录,验证码字体、验证码背景图片以及验证码词库都存在该目录下
|    | -- fonts
|    | -- pictures
|    | -- words
|-- File.py: 定义RandomFileFactory,用来在data目录中获取随机的字体、背景图片和词语
|-- __init__.py: 作为一种良好的习惯,__init__.py不定义任何东西,仅import
|-- Visual: 顾名思义,提供生成图片验证码功能,最关键的部分
|   |-- Backgrounds.py: 定义了几种验证码背景,比如CroppedImage、RandomDots
|   |-- Base.py: 定义ImageCaptcha,把验证码图片的背景、文字、扭曲操作抽象成Layer
|   |-- Distortions.py:扭曲验证码图片,提供了WigglyBlocks和SineWarp两种
|   |-- __init__.py
|   |-- Pictures.py: 定义ImageFactory,继承RandomFileFactory,用来在data/pictures文件夹选背景
|   |-- Tests.py:通过继承ImageFactory实现三个具体验证码类型,通过重写getLayers()方法实现
|   `-- Text.py:定义FontFactory用来选择随机字体,TextLayer用来生成验证码文字layer
`-- Words.py: WordList封装了验证码的词库,从data/words目录的指定词库选择一个词语作为验证码

2. 文件随机选择
File.py定义了RandomFileFactory,后面选择字体、单词和背景图片的class都继承自该类。
dataDir = os.path.join(os.path.split(os.path.abspath(__file__))[0], "data")
class RandomFileFactory(object):                                                                                                
    extensions = []                                                               
    basePath = "."                                                                
                                                                                  
    def __init__(self, *fileList):                                                
        self.fileList = fileList                                                  
        self._fullPaths = None

dataDir指向data文件夹,默认数据是存在该目录。
extensions在具体情景下指定,比如选择图片可能是.png/.jpg,选择字体是.ttf。
fileList指定搜索文件的起始目录列表,_findFullPaths()方法会迭代fileList,把所有符合extensions的文件都加入self._fullPaths,然后提供pick()函数,通过random.choice(self._fullPaths)随机选择。
def _findFullPaths(self):                                                  
        """From our given file list, find a list of full paths to files"""     
        paths = []                                                             
        for name in self.fileList:                                             
            path = os.path.join(dataDir, self.basePath, name)                  
            if os.path.isdir(path):                                            
                for content in os.listdir(path):                               
                    if self._checkExtension(content):                          
                        paths.append(os.path.join(path, content))              
            else:                                                              
                paths.append(path)                                             
        return paths

具体使用:
class ImageFactory(File.RandomFileFactory):                                                              
    extensions = [".png", ".jpeg"]                                                
    basePath = "pictures"                                                     
   
# 选择data/abstract/目录下的随机背景图片                                                                                                                       
abstract = ImageFactory("abstract")

单词的选择没使用RandomFileFactory,而是直接指定文件名,然后加载所有的单词到一个list,同样通过random.choice(list)选择。存在一些过滤,比如单词的最大长度最小长度。  

3. 验证码
先看BaseCaptcha:
class BaseCaptcha(object):                
    minCorrectSolutions = 1                                                    
    maxIncorrectSolutions = 0                                                  
                                                                               
    def __init__(self):                                                        
        self.solutions = []                                                    
        self.valid = True                                                                          
        self.id = randomIdentifier()                                           
        self.creationTime = time.time()

验证码有对应的solution,这里的solution竟然是一个列表。同时,验证码有时效性。
addSolution(self, solution)
testSolutions(self, solutions):大部分应用solutions都只包含一个答案吧。
这个两个方法很简单,略过。

提供了一个Captcha的工厂Factory用来封装验证码的获取、验证:
class Factory(object):                                     
    def __init__(self, lifetime=60*15):                                        
        self.lifetime = lifetime                                               
        self.storedInstances = {}

lifetime定义了验证码的有效时长,默认15分钟。
再看一下其他几个方法:
    def new(self, cls, *args, **kwargs): 生成一个验证码,cls是验证码的类,都定义在Tests.py。每生成一个新的验证,都保存在storedInstance里。
    def get(self, id): 通过id获取验证码
    def clean(self): 迭代self.storedInstances,清除过时的验证码
    def test(self, id, solutions): 测试验证码是否正确,检查之前先调用self.clean()清除所有过期验证码

说到验证码的存储,这里直接存在实例里,但在应用时量太大不靠谱,所以考虑实现,可能是:
1. 缓存:优点是不用手动clean()过期验证码了,没有持久化,但即便缓存系统奔溃了影响也不大。
2. 数据库: 真持久化了反而考虑有没有必要,假设网站崩溃,回复之后大量验证码也都超过过期时间(比如15分钟)了吧?
3. 文件:如果是测试,还不如例子里来的简单呢。


这里逻辑很清晰易懂。有点可以借鉴的就是验证码的id生成器:
def randomIdentifier(alphabet = string.ascii_letters + string.digits,          
                     length = 24):                                             
    return "".join([random.choice(alphabet) for i in xrange(length)])


关于验证码的test()方法,现在有验证码A,客户端输入答案并提交,携带验证码A的id和输入的答案跑去服务器验证结果,如果验证失败,原来的验证码A还存在于服务器端。一般网站的做法是又返回一个新的验证码B,同时把B的id埋在form中,这样用户再输入,验证的便是另一个新的验证码B,而不能多次尝试验证码A的答案。

但,客户端可以把验证码A的id记录下来,第一次失败后,第二次还拿验证码A的id跑去验证,这样就可以实现对一个验证码的多次尝试了。

所以,建议把test()方法改造一下,每个验证码只尝试一次,无论结果正确与否,马上删除。

4. 生成图片验证码
这部分是验证码的最核心部分,也是最难的部分。验证码的作用就是防止spammer,如何生成人类肉眼容易识别和理解但程序通过图像处理难以识别的文字是一门学问。
先看看ImageCaptcha:
class ImageCaptcha(Captcha.BaseCaptcha):                         
    defaultSize = (256,96)                                                                                                                                
    def __init__(self, *args, **kwargs):                                       
        Captcha.BaseCaptcha.__init__(self)                                     
        self._layers = self.getLayers(*args, **kwargs)

ImageCaptcha继承了BaseCaptcha,defaultSize定义了验证码图片的尺寸大小。
_layers属性非常关键,来看getLayers方法便会发现只是返回空的列表[],这个方法定义验证码生成的具体算法,由子类来覆盖实现,后面详细讲。
getImage()方法用来获取验证码图片,它又调用了render()方法,而render方法没做任何实质性的工作,本质上调用了_renderList()方法,直接来看看这个方法,代码如下:
def _renderList(self, layers, img):                                             
        for i in layers:                                                            
            if type(i) == tuple or type(i) == list:                            
                img = self._renderList(i, img)                                 
            else:                                                              
                img = i.render(img) or img                                     
        return img
layers参数就是getLayers()方法子类实现返回的,img则是验证码图片,新生成的:
img = Image.new("RGB", size)

_renderList()方法是,从子类获得Layers,然后,根据依次调用layer.render(img)方法,得到新的img,循环调用下去,最后得到的img就是最终的验证图片。
Layer是什么?验证码图片刚开始只是一张新生成的空白图片(img),然后经过添加背景、添加验证码文字、图片扭曲处理这三个步骤,得到最终的图片。这里的每个步骤都可以看做一个Layer,即抽象成对图片img的一个处理步骤。每个步骤的输入都是最开始的img对象,如何处理呢,不外img.paste()、img.transform()等几个PIL图像处理的常用方法,所以使用python做验证码还需要研究PIL。
另外,layer对象支持返回带list/tuple元素的列表对象。
这里getLayers()方法只返回[]的做法很妙,对Layer的抽象也很妙,参考设计模式的Strategy/Template Pattern。

下面看看如何生成背景图片、添加验证码文字、图片扭曲的具体算法就不介绍了,具体在:
背景图片生成算法:Backgrounds.py文件
添加验证码文字:Text.py(包括字体选择)
图片扭曲算法:Distortions.py(最核心的算法)
分享到:
评论

相关推荐

    基于SVM的验证码破解程序

    svm 一个基于SVM的验证码破解程序 ##起因 弄这个项目的原因,是目前还没有发现一个比较好用的验证码识别模块,目前的验证码识别主要是基于google的光学字符识别Tesseract-OCR如PyOCR,识别精度...生成验证码pycaptcha

    whatmail:简单的python cgi联系表格。 精通utf8,可刮胡子。 可选的验证码(Winograd,Pycaptcha)和gpgme加密

    @TheRealDod的 这是一个简单的cgi联系人表格,可以处理utf-8,这对我来说是至关重要的功能,因为并非我的所有朋友都用英语写信给我:) 它还具有一个。 默认情况下启用它,但是您可以配置whatmail禁用它。...

    利用CNN进行无人售货机的商品识别.zip

    无人机最强算法源码,易于部署和学习交流使用

    node-v9.11.0-sunos-x86.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    ch-PP-OCRv2-det.onnx

    PP-OCR det

    基于TensorFlow的无人机机动飞行LSTM 时序动作网络.zip

    无人机最强算法源码,易于部署和学习交流使用

    ISO 16750-1-2023中文.pdf

    ISO 16750-1-2023中文.pdf

    node-v6.11.3-x86.msi

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    infrared-remote-controller-master

    旅行商问题

    ch-PP-OCRv3-det.onnx

    PP-OCR det

    电赛第二次积分赛无人机,实现循迹、识别图形与其颜色、串口通讯等功能.zip

    无人机最强源码,无人机算法,易于部署和学习交流使用

    node-v10.1.0-linux-arm64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    基于TMS320VC5416 设计DSP最小系统开发板硬件(原理图+PCB)工程文件.zip

    基于TMS320VC5416 设计DSP最小系统开发板硬件(原理图+PCB)工程文,PCB硬件采用2层板设计,大小为99*75mm,USB D型接口供电,包括AD设计的原理图和PCB文件,可以做为你的学习及设计参考。

    node-v6.9.4-x86.msi

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    基于OpenCV+MySQL+QT实现的人脸识别考勤系统源码.zip

    基于OpenCV+MySQL+QT实现的人脸识别考勤系统源码.zip 本资源中的源码都是经过本地编译过可运行的,评审分达到95分以上。资源项目的难度比较适中,内容都是经过助教老师审定过的能够满足学习、使用需求,如果有需要的话可以放心下载使用。 基于OpenCV+MySQL+QT实现的人脸识别考勤系统源码.zip 本资源中的源码都是经过本地编译过可运行的,评审分达到95分以上。资源项目的难度比较适中,内容都是经过助教老师审定过的能够满足学习、使用需求,如果有需要的话可以放心下载使用。 基于OpenCV+MySQL+QT实现的人脸识别考勤系统源码.zip 本资源中的源码都是经过本地编译过可运行的,评审分达到95分以上。资源项目的难度比较适中,内容都是经过助教老师审定过的能够满足学习、使用需求,如果有需要的话可以放心下载使用。 基于OpenCV+MySQL+QT实现的人脸识别考勤系统源码.zip 本资源中的源码都是经过本地编译过可运行的,评审分达到95分以上。资源项目的难度比较适中,内容都是经过助教老师审定过的能够满足学习、使用需求,如果有需要的话可以放心下载使用。

    基于matlab实现的matlab中的通信工具箱中simulink搭建直接序列扩频系统并进行仿真.rar

    基于matlab实现的matlab中的通信工具箱中simulink搭建直接序列扩频系统并进行仿真.rar

    大疆无人机集成.zip

    无人机最强源码,无人机算法,易于部署和学习交流使用

    安卓无人机.zip

    无人机最强源码,无人机算法,易于部署和学习交流使用

    ch_ppocr_mobile_v2.0_rec.onnx

    PP-OCR rec

    node-v11.2.0-linux-s390x.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

Global site tag (gtag.js) - Google Analytics