如何使用Python编写万能验证码?(教你用Python从零写一个验证码)

本文将从多个方面介绍如何使用Python编写万能验证码

一、什么是验证码?

验证码,全称为“图像验证码”,是一种区分用户是计算机还是人的计算机程序。通常,它要求用户输入正确的验证码才能进行某些操作,例如注册账号或提交表单。

一般来说,验证码的主要目的是为了防止计算机程序自动完成某种操作,例如恶意刷票、发送垃圾邮件等。同时,也可以有效防止黑客对某些网站进行暴力破解。

二、Python实现验证码的基本框架

下面我们构建一个简单的验证码生成器。


import random
from PIL import Image, ImageDraw, ImageFont

# 设置验证码的宽度、高度、长度、字体、字体大小
width, height, length = 120, 50, 4
font = ImageFont.truetype("arial.ttf", size=30)

# 生成随机字符串
def random_str(length):
    letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    return "".join(random.choice(letters) for i in range(length))

# 创建并绘制图片
im = Image.new("RGB", (width, height), (255, 255, 255))
draw = ImageDraw.Draw(im)

# 绘制字符串
string = random_str(length)
for i in range(len(string)):
    draw.text(((width / length) * i + 5, 0), string[i], font=font, fill=(0, 0, 0))

# 添加噪点
for i in range(50):
    draw.point((random.randint(0, width), random.randint(0, height)), fill=(0, 0, 0))

# 保存图片并显示
im.save("captcha.png", "PNG")
im.show()

上面的代码使用 Pillow 库(Python Imaging Library 的支持版本)生成了一个包含随机字符串的简单验证码。

三、如何让验证码更安全更难破解?

1、添加干扰线

除了添加噪点之外,我们还可以添加干扰线来增加验证码的破解难度。


# 添加干扰线
for i in range(4):
    draw.line([(random.randint(0, width), random.randint(0, height)),
               (random.randint(0, width), random.randint(0, height))],
              width=1, fill=(0, 0, 0))

上面的代码将在验证码中添加四条不规则的干扰线。

2、使用扭曲效果

除了添加噪点和干扰线之外,我们还可以对验证码进行扭曲,使得验证码对于机器的自动识别更加困难。


# 使用 PIL 内置的 Transform 类进行扭曲
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
          ]
im = im.transform((width, height), Image.PERSPECTIVE, params)
im.show()

使用上述代码可以将验证码扭曲一定程度,增加其难度。

四、如何与Django集成生成验证码?

我们可以将上述代码与 Django 集成,以便在 Django 中生成验证码。


from django.shortcuts import HttpResponse
from PIL import Image, ImageDraw, ImageFont
import random

def captcha(request):
    # 设置验证码的宽度、高度、长度、字体、字体大小
    width, height, length = 120, 50, 4
    font = ImageFont.truetype("arial.ttf", size=30)

    # 生成随机字符串
    def random_str(length):
        letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        return "".join(random.choice(letters) for i in range(length))

    # 创建并绘制图片
    im = Image.new("RGB", (width, height), (255, 255, 255))
    draw = ImageDraw.Draw(im)

    # 绘制字符串
    string = random_str(length)
    request.session['captcha'] = string
    for i in range(len(string)):
        draw.text(((width / length) * i + 5, 0), string[i], font=font, fill=(0, 0, 0))

    # 添加干扰线
    for i in range(4):
        draw.line([(random.randint(0, width), random.randint(0, height)),
                   (random.randint(0, width), random.randint(0, height))],
                  width=1, fill=(0, 0, 0))

    # 使用 PIL 内置的 Transform 类进行扭曲
    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
              ]
    im = im.transform((width, height), Image.PERSPECTIVE, params)

    # 输出
    response = HttpResponse(content_type="image/png")
    im.save(response, "PNG")
    return response

上述代码将生成一个包含随机字符串的验证码,并将验证码存储到 session 中,以便在后续的提交、验证过程中进行验证。

五、总结

本文介绍了如何使用 Python 和 Django 构建一个万能验证码。除了主要的验证码的构建过程,我们还介绍了如何添加干扰线和使用扭曲效果来增加验证码的安全性。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平