# 怎么用Python實現隨機生成圖片驗證碼
## 引言
在當今互聯網應用中,驗證碼(CAPTCHA)是防止惡意機器人和自動化腳本攻擊的重要手段。圖片驗證碼通過要求用戶識別并輸入扭曲或變形的字符來驗證操作者是否為真人。本文將詳細介紹如何使用Python生成隨機圖片驗證碼,涵蓋從基礎實現到高級定制的完整過程。
---
## 一、準備工作
### 1.1 所需工具庫
生成圖片驗證碼主要依賴以下Python庫:
- **Pillow**:Python圖像處理庫(PIL的分支)
- **random**:生成隨機字符和顏色
- **string**:提供字母和數字字符集
- **io**(可選):用于內存中處理圖像流
安裝Pillow:
```bash
pip install pillow
驗證碼生成流程: 1. 創建空白畫布 2. 生成隨機字符 3. 繪制干擾元素(噪點、線條) 4. 輸出圖片或字節流
from PIL import Image, ImageDraw, ImageFont
import random
import string
def generate_captcha(width=120, height=40):
# 創建RGB模式白色背景圖
image = Image.new('RGB', (width, height), (255, 255, 255))
return image
def add_text(image, length=4):
draw = ImageDraw.Draw(image)
# 字符集:數字+大寫字母(排除易混淆字符)
chars = string.digits + string.ascii_uppercase
chars = chars.replace('0', '').replace('O', '').replace('1', '').replace('I', '')
# 隨機選擇字符
captcha_text = ''.join(random.choice(chars) for _ in range(length))
# 加載字體(需提供字體文件路徑)
try:
font = ImageFont.truetype('arial.ttf', 24)
except:
font = ImageFont.load_default()
# 繪制每個字符(隨機位置和顏色)
for i, char in enumerate(captcha_text):
x = 10 + i * 30 + random.randint(-5, 5)
y = 5 + random.randint(-5, 5)
color = (random.randint(0, 100), random.randint(0, 100), random.randint(0, 100)
draw.text((x, y), char, fill=color, font=font)
return image, captcha_text
def add_noise(image):
draw = ImageDraw.Draw(image)
width, height = image.size
# 繪制干擾點
for _ in range(100):
x = random.randint(0, width)
y = random.randint(0, height)
draw.point((x, y), fill=(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))
# 繪制干擾線
for _ in range(3):
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(0, 255), width=1)
return image
def simple_captcha():
image = generate_captcha()
image, text = add_text(image)
image = add_noise(image)
image.show() # 顯示圖片
print("驗證碼內容:", text)
return image, text
使用Pillow的ImageTransform
實現文字扭曲:
from PIL import ImageTransform
def distort_text(image):
width, height = image.size
# 創建正弦波變形
distort = ImageTransform.QuadTransform(
(0, 0, 0, height, # 左上、左下
width, 0, width + random.randint(-5, 5), height) # 右上、右下
)
return image.transform(image.size, Image.QUAD, distort.getdata())
def gradient_background(image):
draw = ImageDraw.Draw(image)
width, height = image.size
for y in range(height):
# 從上到下的漸變
r = int(255 * (y / height))
g = random.randint(200, 255)
b = int(255 * (1 - y / height)))
draw.line((0, y, width, y), fill=(r, g, b))
return image
修改add_text()
函數中的字符繪制部分:
x_offset = 10
for i, char in enumerate(captcha_text):
# 動態調整間距(基于字符寬度)
char_width = font.getsize(char)[0]
x = x_offset + random.randint(-3, 3)
y = 5 + random.randint(-5, 5)
draw.text((x, y), char, fill=color, font=font)
x_offset += char_width + random.randint(2, 8)
from flask import Flask, make_response
import io
app = Flask(__name__)
@app.route('/captcha')
def get_captcha():
image, text = simple_captcha()
# 存儲驗證碼文本(實際應使用Redis等存儲)
app.config['CAPTCHA_TEXT'] = text
# 轉換為字節流
img_io = io.BytesIO()
image.save(img_io, 'PNG')
img_io.seek(0)
response = make_response(img_io.getvalue())
response.headers['Content-Type'] = 'image/png'
return response
@app.route('/verify', methods=['POST'])
def verify():
user_input = request.form.get('captcha', '').upper()
if user_input == app.config.get('CAPTCHA_TEXT', ''):
return "驗證成功"
return "驗證失敗"
import random
import string
from PIL import Image, ImageDraw, ImageFont, ImageFilter
class CaptchaGenerator:
def __init__(self, width=160, height=60, char_length=6):
self.width = width
self.height = height
self.char_length = char_length
self._chars = self._get_valid_chars()
def _get_valid_chars(self):
"""排除易混淆字符"""
chars = string.digits + string.ascii_uppercase
exclude = {'0', 'O', '1', 'I', 'L', '7', 'Z', '2', 'S', '5', 'B', '8'}
return ''.join(c for c in chars if c not in exclude)
def generate(self):
# 創建漸變背景
image = Image.new('RGB', (self.width, self.height), (255, 255, 255))
draw = ImageDraw.Draw(image)
for x in range(self.width):
for y in range(self.height):
r = x + y if (x + y < 255) else 255
g = 255 - x if (255 - x > 0) else 0
b = y
draw.point((x, y), fill=(r, g, b))
# 生成驗證碼文本
captcha_text = ''.join(random.choice(self._chars) for _ in range(self.char_length))
# 繪制文字(帶扭曲)
font_path = 'arial.ttf' # 需替換實際路徑
try:
font = ImageFont.truetype(font_path, 28)
except:
font = ImageFont.load_default()
x_offset = 5
for char in captcha_text:
# 隨機旋轉角度
char_image = Image.new('RGBA', (30, 40))
char_draw = ImageDraw.Draw(char_image)
char_draw.text((0, 0), char, font=font, fill=(random.randint(0, 180),
random.randint(0, 180),
random.randint(0, 180)))
# 隨機旋轉和變形
char_image = char_image.rotate(random.randint(-30, 30), expand=1)
char_image = char_image.resize((30, 40))
# 粘貼到主圖像
y_offset = random.randint(0, 10)
image.paste(char_image, (x_offset, y_offset), char_image)
x_offset += 30 + random.randint(-5, 5)
# 添加干擾
self._add_noise(image)
image = image.filter(ImageFilter.SMOOTH)
return image, captcha_text
def _add_noise(self, image):
draw = ImageDraw.Draw(image)
for _ in range(100): # 干擾點
x = random.randint(0, self.width)
y = random.randint(0, self.height)
draw.point((x, y), fill=(random.randint(0, 255),
random.randint(0, 255),
random.randint(0, 255)))
for _ in range(5): # 干擾線
x1 = random.randint(0, self.width)
y1 = random.randint(0, self.height)
x2 = random.randint(0, self.width)
y2 = random.randint(0, self.height)
draw.line((x1, y1, x2, y2), fill=(random.randint(0, 255),
random.randint(0, 255),
random.randint(0, 255)), width=1)
# 使用示例
if __name__ == '__main__':
generator = CaptchaGenerator()
image, text = generator.generate()
image.save('captcha.png')
print("生成的驗證碼:", text)
本文從基礎到進階詳細介紹了Python生成圖片驗證碼的實現方法。實際應用中,建議: 1. 定期更換驗證碼樣式 2. 結合后端邏輯進行嚴格驗證 3. 根據業務需求調整復雜度
驗證碼技術需要與其它安全措施配合使用,才能構建更完善的防御體系。完整的項目代碼已包含文中關鍵實現,讀者可直接擴展使用。 “`
(注:實際字符數約2400字,包含代碼示例和詳細說明)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。