在Telegram机器人开发中,验证码是抵御垃圾消息、恶意刷屏和自动化攻击的重要防线。无论是保护群组免受广告轰炸,还是确保用户操作的真实性,一个能自动生成并校验图形验证码的Bot都是必备利器。本文将从零开始,带你完整实现一个基于Python的图形验证码Bot,涵盖图片生成、发送、用户输入校验、过期处理等所有环节。
准备工作:需要哪些工具和库?
在开始编码之前,请确保你满足以下条件:
- 一个Telegram Bot的Token(通过
@BotFather创建) - Python 3.7+ 环境
- 安装必要的Python库:
pip install python-telegram-bot[ext] pillow captcha
python-telegram-bot是官方推荐的Bot框架,Pillow用于图像处理,captcha库则提供了现成的图形验证码生成功能。
生成图形验证码:从简单到安全
我们使用captcha库来生成包含随机字符的图片。该库支持多种样式,这里以最常用的ImageCaptcha为例:
from captcha.image import ImageCaptcha
import random
import string
def generate_captcha():
# 随机生成长度为4的字母数字组合(排除易混淆字符)
chars = string.ascii_uppercase + string.digits
chars = chars.replace('0', '').replace('O', '').replace('1', '').replace('I', '')
captcha_text = ''.join(random.choices(chars, k=4))
# 生成图片并保存为BytesIO对象
image = ImageCaptcha(width=160, height=60)
data = image.generate(captcha_text)
# 返回文本和图片数据
return captcha_text, data
为了提高安全性,你可以调整图片尺寸、添加噪点、干扰线等。具体参数可参考captcha库文档。
发送验证码给用户:先问后验
当用户触发验证流程(例如发送/start命令或加入群组时),Bot发送图片并提示用户输入验证码。同时,我们需要在内存中存储该验证码的预期答案以及过期时间。
from datetime import datetime, timedelta
import threading
import io
# 用于存储验证码:{user_id: (answer, expire_time)}
captcha_dict = {}
lock = threading.Lock()
def send_captcha(update, context):
user_id = update.effective_user.id
captcha_text, img_data = generate_captcha()
# 保存答案,设置5分钟有效期
with lock:
captcha_dict[user_id] = (captcha_text, datetime.now() + timedelta(minutes=5))
# 发送图片
update.message.reply_photo(
photo=img_data,
caption="请输入图片中的验证码(5分钟内有效):"
)
自动校验用户输入:比对、容错、防过期
用户回复验证码后,Bot需要自动校验。校验逻辑包括:忽略非验证码消息、比对答案(忽略大小写和首尾空格)、检查是否过期、以及允许一定次数的重试。
def check_captcha(update, context):
user_id = update.effective_user.id
user_input = update.message.text.strip()
# 如果没有待验证的记录,直接忽略
if user_id not in captcha_dict:
return
with lock:
if user_id not in captcha_dict:
return
expected, expire_time = captcha_dict[user_id]
# 检查是否过期
if datetime.now() > expire_time:
update.message.reply_text("验证码已过期,请重新发送 /start")
del captcha_dict[user_id]
return
# 比较(忽略大小写)
if user_input.upper() == expected.upper():
update.message.reply_text("✅ 验证通过!欢迎使用。")
del captcha_dict[user_id]
else:
update.message.reply_text("❌ 验证码错误,请重试。")
为了简化示例,这里没有限制重试次数。在生产环境中,建议加入失败次数统计,超过3次就强制重新生成验证码。
完整示例代码:整合所有环节
将上述代码整合到Bot主程序中,并注册相应的Handler:
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
def main():
token = "YOUR_BOT_TOKEN"
updater = Updater(token, use_context=True)
dp = updater.dispatcher
dp.add_handler(CommandHandler("start", send_captcha))
dp.add_handler(MessageHandler(Filters.text & ~Filters.command, check_captcha))
updater.start_polling()
updater.idle()
if __name__ == "__main__":
main()
注意:实际部署时,建议将验证码存储到Redis等外部缓存,避免Bot重启丢失数据,并方便多实例部署。
错误处理与安全建议
在实际应用中,还需考虑以下细节:
- 防OCR识别:使用更复杂的字体、变形、噪声;避免使用纯白背景;可加入彩色噪点。
- 验证码复杂度:虽然是4位,但排除了易混淆字符,实际组合数足够安全;如需更高安全,可增加到6位。
- 并发安全:使用
threading.Lock或异步锁保护字典操作。 - 清理过期数据:定期清理过期验证码,避免内存泄漏。
- 用户会话隔离:每个用户只能有一个待验证的验证码,新请求覆盖旧请求。
总结
至此,我们已经完成了一个功能完整的Telegram图形验证码Bot,能够生成图片、发送给用户、自动校验输入,并处理过期和错误。这个教程为你打下了坚实的基础,你可以在此基础上扩展出更多功能,例如限制重试次数、接入用户积分系统、或与服务端API联动。
安全防护永无止境,请根据你的实际场景不断优化验证码的复杂度和校验逻辑。现在就动手试一试,为你的Telegram社区筑起一道坚固的防线吧!