from PIL import Image, ImageDraw, ImageFont, ImageFilter import random import string def generate_text_captcha(width=200, height=80, char_count=4, font_size=40): """生成普通文字验证码(带干扰线和噪点)""" # 1. 创建空白图片(背景色随机浅灰) bg_color = (random.randint(200, 255), random.randint(200, 255), random.randint(200, 255)) image = Image.new('RGB', (width, height), bg_color) draw = ImageDraw.Draw(image) # 2. 生成随机字符(字母+数字) chars = random.sample(string.ascii_letters + string.digits, char_count) captcha_text = ''.join(chars) # 3. 加载字体(需替换为本地字体路径,若无则注释此行用默认字体) try: font = ImageFont.truetype('simhei.ttf', font_size) # 黑体,需系统存在该字体 except: font = ImageFont.load_default() # 默认字体 # 4. 绘制文字(随机颜色、位置、旋转角度) for i, char in enumerate(captcha_text): # 文字颜色(深色,与背景区分) text_color = (random.randint(0, 100), random.randint(0, 100), random.randint(0, 100)) # 文字位置(避免超出边界) x = 10 + i * (width // char_count) y = random.randint(10, height - font_size - 10) # 随机旋转(-15到15度) angle = random.randint(-15, 15) # 创建单个字符的临时图片并旋转 char_image = Image.new('RGBA', (font_size, font_size), (255, 255, 255, 0)) char_draw = ImageDraw.Draw(char_image) char_draw.text((0, 0), char, font=font, fill=text_color) char_image_rotated = char_image.rotate(angle, expand=True) # 粘贴到主图 image.paste(char_image_rotated, (x, y), char_image_rotated) # 5. 绘制干扰线(5-8条) for _ in range(random.randint(5, 8)): line_color = (random.randint(100, 200), random.randint(100, 200), random.randint(100, 200)) # 随机起点和终点 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=line_color, width=2) # 6. 绘制噪点(100-200个) for _ in range(random.randint(100, 200)): noise_color = (random.randint(50, 150), random.randint(50, 150), random.randint(50, 150)) x = random.randint(0, width) y = random.randint(0, height) draw.point((x, y), fill=noise_color) # 7. 轻微模糊处理 image = image.filter(ImageFilter.GaussianBlur(radius=0.5)) return image, captcha_text # 生成并保存普通验证码 captcha_img, captcha_code = generate_text_captcha() captcha_img.save('text_captcha.png') print(f"普通验证码文字:{captcha_code}") def generate_click_captcha(width=400, height=300, total_chars=12, target_count=4, font_size=30): """生成点击式文字验证码(返回目标文字坐标)""" # 1. 创建背景图(随机渐变色) image = Image.new('RGB', (width, height), (240, 240, 240)) draw = ImageDraw.Draw(image) # 2. 生成随机字符集(中文+字母,增加复杂度) # 中文样本(可扩展) chinese_chars = '一二三四五六七八九十甲乙丙丁戊己庚辛壬癸金木水火土' all_chars = list(chinese_chars + string.ascii_letters) random.shuffle(all_chars) # 总字符数和目标字符(需点击的4个) used_chars = all_chars[:total_chars] target_chars = random.sample(used_chars, target_count) # 3. 加载字体(支持中文) try: font = ImageFont.truetype('simhei.ttf', font_size) # 需系统有中文字体 except: font = ImageFont.load_default() # 4. 随机分布字符并记录坐标 char_positions = {} # 存储 {字符: (中心x, 中心y)} for char in used_chars: # 随机位置(避免边缘) x = random.randint(font_size, width - font_size) y = random.randint(font_size, height - font_size) # 随机颜色(区分度高) color = (random.randint(0, 150), random.randint(0, 150), random.randint(0, 150)) # 随机旋转角度 angle = random.randint(-30, 30) # 绘制带旋转的字符 char_img = Image.new('RGBA', (font_size*2, font_size*2), (255, 255, 255, 0)) char_draw = ImageDraw.Draw(char_img) char_draw.text((font_size//2, font_size//2), char, font=font, fill=color) char_rotated = char_img.rotate(angle, expand=True) # 计算旋转后粘贴的位置(使中心对齐(x,y)) rx, ry = char_rotated.size paste_x = x - rx//2 paste_y = y - ry//2 image.paste(char_rotated, (paste_x, paste_y), char_rotated) # 记录中心坐标 char_positions[char] = (x, y) # 5. 添加干扰元素(网格线) for x in range(0, width, 40): draw.line([(x, 0), (x, height)], fill=(200, 200, 200), width=1) for y in range(0, height, 40): draw.line([(0, y), (width, y)], fill=(200, 200, 200), width=1) # 6. 获取目标字符的坐标 target_positions = {char: char_positions[char] for char in target_chars} return image, target_chars, target_positions # 生成并保存点击式验证码 click_img, target_chars, target_coords = generate_click_captcha() click_img.save('click_captcha.png') print(f"需点击的文字:{target_chars}") print(f"对应坐标:{target_coords}")