Python を使用して写真の番号の確認コードを生成する

ここに画像の説明を挿入
多くの Web サイトでは、プログラムによる悪意のある登録を防止し、Web サイトのセキュリティを確保するために、登録時に確認コードの入力を求められます。

1.枕

PIL(Python Imaging Library)強力な Python 画像処理ライブラリですが、それのみをサポートしています。Pillow はpython2.7PIL のブランチですが、Pillow は python3.x をサポートし、PIL 自体よりも動的な画像処理ライブラリに開発されています。検証コードの生成には Pillow を使用します。インストール方法は、

pip install Pillow

2. 指定したサイズとランダムな色の画像を生成します

2.1 ランダムな色

色処理は (r, g, b) 形式を使用します。r、g、b の範囲は [0, 255]、モジュール方式を使用してrandom3randintつの乱数を生成します。

def random_color():
    c1 = random.randint(0, 255)
    c2 = random.randint(0, 255)
    c3 = random.randint(0, 255)
    return c1, c2, c3

2.2 指定したサイズの画像を生成する

def random_color():
    c1 = random.randint(0, 255)
    c2 = random.randint(0, 255)
    c3 = random.randint(0, 255)
    return c1, c2, c3

def generate_picture(width=120, height=35):
    image = Image.new('RGB', (width, height), random_color())
    return image

if __name__ == '__main__':
    image = generate_picture()
    image.save('test.png')

ここに画像の説明を挿入

あとは、ランダムな色の画像を生成し、その画像上にランダムな数字と文字を書き込むだけです。

3.絵の上にランダムな数字と文字を書きます

3.1 乱数と文字の生成

def get_random_str():
    '''
    获取一个随机字符, 数字或小写字母
    :return:
    '''
    random_num = str(random.randint(0, 9))
    random_low_alpha = chr(random.randint(97, 122))
    random_char = random.choice([random_num, random_low_alpha])
    return random_char

ランダムモジュールが提供するランダム関数を使用して、指定された長さの文字列を生成します。

3.2 画像オブジェクト上に数字や文字を描画する

def draw_str(count, image, font_size):
    """
    在图片上写随机字符
    :param count: 字符数量
    :param image: 图片对象
    :param font_size: 字体大小
    :return:
    """
    draw = ImageDraw.Draw(image)
    # 获取一个font字体对象参数是ttf的字体文件的目录,以及字体的大小
    font_file = os.path.join('Andale Mono.ttf')
    font = ImageFont.truetype(font_file, size=font_size)
    temp = []
    for i in range(count):
        random_char = random_str()
        draw.text((10+i*30, -2), random_char, random_color(), font=font)
        temp.append(random_char)

    valid_str = "".join(temp)    # 验证码
    return valid_str, image

if __name__ == '__main__':
    image = generate_picture()
    valid_str, image = draw_str(4, image, 35)
    image.save('test.png')

ここに画像の説明を挿入

オブジェクトを作成しImageDraw.Draw、画像上にランダムな文字を描画します。フォントを設定できます。私はそれを使用しましたAndale Mono.ttf。Mac コンピューター上のディレクトリでフォントを見つけます/System/Library/Fonts。他のシステムにも独自のフォント ファイルがあり、フォント ファイルを同じディレクトリにコピーします。スクリプト。

4. ノイズを作成する

認証コードが簡単に解読されないようにするには、画像にノイズを加え、ランダムに数本の線を描き、ランダムにいくつかの点を描く必要があります。

def noise(image, width=120, height=35, line_count=3, point_count=20):
    '''

    :param image: 图片对象
    :param width: 图片宽度
    :param height: 图片高度
    :param line_count: 线条数量
    :param point_count: 点的数量
    :return:
    '''
    draw = ImageDraw.Draw(image)
    for i in range(line_count):
        x1 = random.randint(0, width)
        x2 = random.randint(0, width)
        y1 = random.randint(0, height)
        y2 = random.randint(0, height)
        draw.line((x1, y1, x2, y2), fill=random_color())

        # 画点
        for i in range(point_count):
            draw.point([random.randint(0, width), random.randint(0, height)], fill=random_color())
            x = random.randint(0, width)
            y = random.randint(0, height)
            draw.arc((x, y, x + 4, y + 4), 0, 90, fill=random_color())

    return image


if __name__ == '__main__':
    image = generate_picture()
    valid_str, image = draw_str(4, image, 35)
    image = noise(image)
    image.save('test.png')

ここに画像の説明を挿入

5.base64でエンコードされた画像を生成する

実際には、Web サイト登録用の確認コード画像を生成する場合、一般的には、それを画像ファイルに保存しません。これは、完全に不要な小さな画像が多数生成されるためです。BytesIO画像の内容をオブジェクトに保存し、最終base64的にエンコードされた画像を生成すると、次の形式の文字列がフロントエンドに返されます。

data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAH...

data:image/jpeg;base64このセクションは固定された方法で記述されており、カンマの残りは画像の Base64 エンコード文字列です。

def valid_code():
    """
    生成图片验证码,并对图片进行base64编码
    :return:
    """
    image = generate_picture()
    valid_str, image = draw_str(4, image, 35)
    image = noise(image)

    f = BytesIO()
    image.save(f, 'png')        # 保存到BytesIO对象中, 格式为png
    data = f.getvalue()
    f.close()

    encode_data = base64.b64encode(data)
    data = str(encode_data, encoding='utf-8')
    img_data = "data:image/jpeg;base64,{data}".format(data=data)
    return valid_str, img_data

if __name__ == '__main__':
    print(valid_code())

6. すべてのコード

検証コードの画像を生成するプロセスを説明するために、プロセス全体を分解します。コードは分解されて乱雑になっていますが、実際のアプリケーションで使用するためにこれらのコードを統合できます。

import os
import random
import base64
from io import BytesIO
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont


def random_color():
    c1 = random.randint(0, 255)
    c2 = random.randint(0, 255)
    c3 = random.randint(0, 255)
    return c1, c2, c3


def generate_picture(width=120, height=35):
    image = Image.new('RGB', (width, height), random_color())
    return image


def random_str():
    '''
    获取一个随机字符, 数字或小写字母
    :return:
    '''
    random_num = str(random.randint(0, 9))
    random_low_alpha = chr(random.randint(97, 122))
    random_char = random.choice([random_num, random_low_alpha])
    return random_char

def draw_str(count, image, font_size):
    """
    在图片上写随机字符
    :param count: 字符数量
    :param image: 图片对象
    :param font_size: 字体大小
    :return:
    """
    draw = ImageDraw.Draw(image)
    # 获取一个font字体对象参数是ttf的字体文件的目录,以及字体的大小
    font_file = os.path.join('Andale Mono.ttf')
    font = ImageFont.truetype(font_file, size=font_size)
    temp = []
    for i in range(count):
        random_char = random_str()
        draw.text((10+i*30, -2), random_char, random_color(), font=font)
        temp.append(random_char)

    valid_str = "".join(temp)    # 验证码
    return valid_str, image


def noise(image, width=120, height=35, line_count=3, point_count=20):
    '''

    :param image: 图片对象
    :param width: 图片宽度
    :param height: 图片高度
    :param line_count: 线条数量
    :param point_count: 点的数量
    :return:
    '''
    draw = ImageDraw.Draw(image)
    for i in range(line_count):
        x1 = random.randint(0, width)
        x2 = random.randint(0, width)
        y1 = random.randint(0, height)
        y2 = random.randint(0, height)
        draw.line((x1, y1, x2, y2), fill=random_color())

        # 画点
        for i in range(point_count):
            draw.point([random.randint(0, width), random.randint(0, height)], fill=random_color())
            x = random.randint(0, width)
            y = random.randint(0, height)
            draw.arc((x, y, x + 4, y + 4), 0, 90, fill=random_color())

    return image


def valid_code():
    """
    生成图片验证码,并对图片进行base64编码
    :return:
    """
    image = generate_picture()
    valid_str, image = draw_str(4, image, 35)
    image = noise(image)

    f = BytesIO()
    image.save(f, 'png')        # 保存到BytesIO对象中, 格式为png
    data = f.getvalue()
    f.close()

    encode_data = base64.b64encode(data)
    data = str(encode_data, encoding='utf-8')
    img_data = "data:image/jpeg;base64,{data}".format(data=data)
    return valid_str, img_data

if __name__ == '__main__':
    print(valid_code())

おすすめ

転載: blog.csdn.net/weixin_45277161/article/details/132635641