本文目录导读:

我来分享几种生成验证码的脚本方法,从简单到复杂都有:
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;
?>
使用建议
- 字符集:避免使用容易混淆的字符(如0和O,1和l)
- 复杂度:根据安全性需求调整干扰程度
- 存储:验证码需要与session关联,设置过期时间
- 可访问性:考虑提供语音验证码选项
- 安全性:存储MD5哈希值而非明文
选择哪种方案取决于你的技术栈和需求复杂度,如果需要更具体的实现细节,可以告诉我你的使用场景!
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播