怎么用脚本生成验证码

wen 实用脚本 2

本文目录导读:

怎么用脚本生成验证码

  1. Python + Pillow(最常用)
  2. Node.js + canvas
  3. 更安全的方案(带渐变和纹理)
  4. 简单的PHP版本
  5. 使用建议

我来分享几种生成验证码的脚本方法,从简单到复杂都有:

Python + Pillow(最常用)

基础数字字母验证码

from PIL import Image, ImageDraw, ImageFont
import random
import string
def generate_captcha(width=200, height=80, length=4):
    # 创建空白图片
    image = Image.new('RGB', (width, height), (255, 255, 255))
    draw = ImageDraw.Draw(image)
    # 验证码字符
    chars = string.ascii_uppercase + string.digits
    captcha_text = ''.join(random.choice(chars) for _ in range(length))
    # 绘制字符
    for i, char in enumerate(captcha_text):
        # 随机颜色
        color = (random.randint(0, 150), 
                random.randint(0, 150), 
                random.randint(0, 150))
        # 随机位置
        x = 20 + i * 40
        y = random.randint(10, 30)
        # 绘制文本
        draw.text((x, y), char, fill=color, font=None)
    # 添加干扰线
    for _ in range(5):
        x1 = random.randint(0, width)
        y1 = random.randint(0, height)
        x2 = random.randint(0, width)
        y2 = random.randint(0, height)
        draw.line((x1, y1, x2, y2), 
                 fill=(random.randint(150, 255),)*3, width=2)
    # 添加噪点
    for _ in range(100):
        x = random.randint(0, width)
        y = random.randint(0, height)
        draw.point((x, y), fill=(random.randint(0, 255),)*3)
    return image, captcha_text
# 使用示例
image, text = generate_captcha()
image.save('captcha.png')
print(f"验证码: {text}")

带干扰线和扭曲的验证码

from PIL import Image, ImageDraw, ImageFont, ImageFilter
import random
import string
def generate_complex_captcha():
    # 图片大小
    width, height = 200, 80
    image = Image.new('RGB', (width, height), 'white')
    draw = ImageDraw.Draw(image)
    # 自定义字体(需要系统字体)
    try:
        font = ImageFont.truetype("arial.ttf", 36)
    except:
        font = ImageFont.load_default()
    # 生成随机字符
    chars = ''.join(random.choices(string.ascii_uppercase + string.digits, k=4))
    # 绘制字符并添加随机旋转
    for i, char in enumerate(chars):
        color = (random.randint(0, 100), 
                random.randint(0, 100), 
                random.randint(0, 100))
        # 创建单个字符的临时图片
        char_img = Image.new('RGB', (50, 50), 'white')
        char_draw = ImageDraw.Draw(char_img)
        char_draw.text((5, 5), char, fill=color, font=font)
        # 随机旋转
        angle = random.randint(-30, 30)
        char_img = char_img.rotate(angle, expand=True)
        # 粘贴到主图
        position = (10 + i * 45, random.randint(5, 15))
        image.paste(char_img, position)
    # 添加背景干扰元素
    for i in range(10):
        draw.line(
            [(random.randint(0, width), random.randint(0, height)),
             (random.randint(0, width), random.randint(0, height))],
            fill=(random.randint(150, 255),) * 3,
            width=1
        )
    # 添加椭圆干扰
    for i in range(3):
        x1 = random.randint(0, width)
        y1 = random.randint(0, height)
        draw.ellipse([x1, y1, x1+20, y1+15], 
                    outline=(random.randint(100, 200),)*3)
    return image, chars
# 生成并保存
image, code = generate_complex_captcha()
image.save('complex_captcha.png')

Node.js + canvas

const Canvas = require('canvas');
const { createCanvas } = Canvas;
function generateCaptcha() {
    const width = 200;
    const height = 80;
    const canvas = createCanvas(width, height);
    const ctx = canvas.getContext('2d');
    // 背景
    ctx.fillStyle = '#f0f0f0';
    ctx.fillRect(0, 0, width, height);
    // 生成随机字符
    const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
    let captchaText = '';
    for (let i = 0; i < 4; i++) {
        captchaText += chars[Math.floor(Math.random() * chars.length)];
    }
    // 绘制字符
    for (let i = 0; i < captchaText.length; i++) {
        ctx.font = `${30 + Math.random() * 10}px Arial`;
        ctx.fillStyle = `rgb(${Math.random()*100}, ${Math.random()*100}, ${Math.random()*100})`;
        ctx.setTransform(
            Math.cos(rotation), Math.sin(rotation),
            -Math.sin(rotation), Math.cos(rotation),
            x, y
        );
        ctx.fillText(captchaText[i], 20 + i * 40, 50);
    }
    // 添加干扰线
    for (let i = 0; i < 5; i++) {
        ctx.beginPath();
        ctx.moveTo(Math.random() * width, Math.random() * height);
        ctx.lineTo(Math.random() * width, Math.random() * height);
        ctx.strokeStyle = `rgba(${Math.random()*255}, ${Math.random()*255}, ${Math.random()*255}, 0.5)`;
        ctx.stroke();
    }
    return {
        image: canvas.toBuffer(),
        text: captchaText
    };
}
// 使用
const { image, text } = generateCaptcha();
require('fs').writeFileSync('captcha.png', image);

更安全的方案(带渐变和纹理)

from PIL import Image, ImageDraw, ImageFont, ImageFilter
import numpy as np
import random
def generate_advanced_captcha():
    width, height = 240, 80
    image = Image.new('RGB', (width, height), 'white')
    draw = ImageDraw.Draw(image)
    # 渐变背景
    for x in range(width):
        for y in range(height):
            # 创建渐变效果
            r = int(200 + 55 * (x / width))
            g = int(200 + 55 * (y / height))
            b = int(200)
            draw.point((x, y), fill=(r, g, b))
    # 字符叠加
    chars = ''.join(random.choices('ABCDEFGHJKLMNPQRSTUVWXYZ23456789', k=4))
    font = ImageFont.truetype("arial.ttf", 36)
    for i, char in enumerate(chars):
        # 创建字符层
        char_layer = Image.new('RGBA', (60, 60), (0, 0, 0, 0))
        char_draw = ImageDraw.Draw(char_layer)
        char_draw.text((5, 5), char, font=font, 
                      fill=(random.randint(0, 80),) * 3)
        # 旋转和扭曲
        char_layer = char_layer.rotate(random.randint(-25, 25), 
                                     reshape=True)
        char_layer = char_layer.resize((45, 45))
        # 合成
        x = 10 + i * 55
        y = 15 + random.randint(-5, 5)
        image.paste(char_layer, (x, y), char_layer)
    # 高斯模糊
    image = image.filter(ImageFilter.GaussianBlur(0.5))
    return image, chars
# 使用
image, code = generate_advanced_captcha()
image.save('advanced_captcha.png')

简单的PHP版本

<?php
function generateCaptcha($width = 200, $height = 80) {
    // 创建图片
    $image = imagecreatetruecolor($width, $height);
    $bg_color = imagecolorallocate($image, 255, 255, 255);
    imagefill($image, 0, 0, $bg_color);
    // 生成随机字符
    $chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
    $captcha = '';
    for ($i = 0; $i < 4; $i++) {
        $captcha .= $chars[rand(0, strlen($chars) - 1)];
    }
    // 写入字符
    for ($i = 0; $i < strlen($captcha); $i++) {
        $color = imagecolorallocate($image, 
            rand(0, 100), rand(0, 100), rand(0, 100));
        $angle = rand(-20, 20);
        // 使用直线模拟字符
        imagestring($image, 5, 20 + $i * 40, rand(10, 40), 
                   $captcha[$i], $color);
    }
    // 添加干扰线
    for ($i = 0; $i < 5; $i++) {
        $color = imagecolorallocate($image, 
            rand(150, 200), rand(150, 200), rand(150, 200));
        imageline($image, rand(0, $width), rand(0, $height),
                 rand(0, $width), rand(0, $height), $color);
    }
    // 输出
    header('Content-Type: image/png');
    imagepng($image);
    imagedestroy($image);
    return $captcha;
}
// 调用
$code = generateCaptcha();
session_start();
$_SESSION['captcha'] = $code;
?>

使用建议

  1. 字符集:避免使用容易混淆的字符(如0和O,1和l)
  2. 复杂度:根据安全性需求调整干扰程度
  3. 存储:验证码需要与session关联,设置过期时间
  4. 可访问性:考虑提供语音验证码选项
  5. 安全性:存储MD5哈希值而非明文

选择哪种方案取决于你的技术栈和需求复杂度,如果需要更具体的实现细节,可以告诉我你的使用场景!

抱歉,评论功能暂时关闭!