How to easily identify the verification code through serverless?

Time:2021-10-16

How to easily identify the verification code through serverless?

Author Jiang Yu
Source Serverless official account

preface

The concept of serverless has attracted much attention since it was put forward. Especially in recent years, serverless has radiated unprecedented vitality. Engineers in various fields are trying to combine serverless architecture with their own work in order to obtain the “technical dividend” brought by serverless architecture.

Captcha is the abbreviation of “fully automated Public Turing test to tell computers and humans apart”. It is a public automatic program to distinguish whether the user is a computer or a human. It can prevent malicious password cracking, ticket swiping and Forum irrigation, and effectively prevent a hacker from constantly trying to log in to a specific registered user by brute force cracking with a specific program. In fact, verification code is a common way for many websites. We use a relatively simple way to realize this function. Captcha’s question is generated and judged by the computer, but this question can only be answered by human beings, and the computer cannot answer it, so the user who answers the question can be regarded as human. To put it bluntly, the verification code is the code used to verify whether it is accessed by people or machines.

So what sparks will the verification code recognition in the field of artificial intelligence collide with the serverless architecture?In this paper, the verification code recognition function will be realized through serverless architecture and convolutional neural network (CNN) algorithm.

On verification code

The development of verification code can be said to be very rapid. From the simple digital verification code at the beginning, to the later number + letter verification code, and then to the later number + letter + Chinese verification code and graphic image verification code, there are more and more simple verification code materials. From the form of verification code, it is also different. Input, click, drag, SMS verification code and voice verification code

BiliBili’s login verification code includes a variety of modes, such as sliding the slider for verification:

How to easily identify the verification code through serverless?

For example, verify by clicking on the text in turn:

How to easily identify the verification code through serverless?

The verification codes of Baidu Post Bar, Zhihu, Google and other related websites are different, such as selecting the text being written, selecting the picture including the specified object, and clicking the characters in the picture in order.

The identification of the verification code may vary according to the type of verification code. Of course, the simplest verification code may be the original text verification code:

How to easily identify the verification code through serverless?

Even for text verification codes, there are many differences, such as simple digital verification code, simple number + letter verification code, text verification code, including calculation in verification code, adding some interference to simple verification code to become complex verification code, etc.

Verification code identification

1. Simple verification code identification

Verification code recognition is an ancient research field, which is simply the process of transforming the text on the picture into text. In recent years, with the development of big data, the majority of crawler engineers have higher and higher requirements for the identification of verification codes when fighting against anti crawling strategies. In the era of simple verification code, the identification of verification code is mainly aimed at the text verification code. Each part of the verification code is cut through image cutting, and then the similarity of each cutting unit is compared to obtain the most possible results. Finally, the verification code is spliced, such as:

How to easily identify the verification code through serverless?

Binarization and other operations:

How to easily identify the verification code through serverless?

Cut after completion:

How to easily identify the verification code through serverless?

It is relatively easy to recognize each character after cutting and finally splicing.

However, with the development of time, when this simple verification code gradually can not meet the problem of judging “whether it is a person or a machine”, the verification code has been slightly upgraded, that is, some interference lines have been added on the verification code, or the verification code has been seriously distorted, increasing strong color block interference, such as the verification code of Dynadot website:

How to easily identify the verification code through serverless?

There are not only image distortion and overlap, but also interference lines and color patches. At this time, if you want to identify the verification code, simple cutting recognition is difficult to obtain good results. At this time, good results can be obtained through in-depth learning.

2. Verification code identification based on CNN

Convolutional neural network (CNN) is a feedforward neural network. Artificial neurons can respond to surrounding units for large-scale image processing. Convolution neural network includes convolution layer and pooling layer.

How to easily identify the verification code through serverless?

As shown in the figure, the left figure is a traditional neural network, and its basic structure is: input layer, hidden layer and output layer. The right figure is a convolutional neural network, which is composed of input layer, output layer, convolution layer, pooling layer and full connection layer. Convolutional neural network is actually an extension of neural network. In fact, in terms of structure, there is no difference between simple CNN and simple NN (of course, complex CNN with special structure will be quite different from NN). Compared with the traditional neural network, CNN greatly reduces the number of network parameters in the actual effect, so that we can train a better model with fewer parameters, get twice the result with half the effort, and effectively avoid over fitting. Similarly, due to the parameter sharing of filter, we can still recognize features even if the image has a certain translation operation, which is called “translation invariance”. Therefore, the model is more robust.

1) Verification code generation

The generation of verification code is a very important step, because this part of verification code will be used as our training set and test set. At the same time, what type of verification code our model can identify is also related to this part.

# coding:utf-8
import random
import numpy as np
from PIL import Image
from captcha.image import ImageCaptcha
CAPTCHA_LIST = [eve for eve in "0123456789abcdefghijklmnopqrsruvwxyzABCDEFGHIJKLMOPQRSTUVWXYZ"]
CAPTCHA_ Len = 4 # verification code length
CAPTCHA_ Height = 60 # verification code height
CAPTCHA_ Width = 160 # verification code width
randomCaptchaText = lambda char=CAPTCHA_LIST, size=CAPTCHA_LEN: "".join([random.choice(char) for _ in range(size)])
def genCaptchaTextImage(width=CAPTCHA_WIDTH, height=CAPTCHA_HEIGHT, save=None):
    image = ImageCaptcha(width=width, height=height)
    captchaText = randomCaptchaText()
    if save:
        image.write(captchaText, './img/%s.jpg' % captchaText)
    return captchaText, np.array(Image.open(image.generate(captchaText)))
print(genCaptchaTextImage(save=True))

Through the above code, a simple Chinese and English verification code can be generated:

How to easily identify the verification code through serverless?

2) Model training

The code of model training is as follows (part of the code comes from the network).

Util.py file is mainly some extracted public methods:

# -*- coding:utf-8 -*-
import numpy as np
from captcha_gen import genCaptchaTextImage
from captcha_gen import CAPTCHA_LIST, CAPTCHA_LEN, CAPTCHA_HEIGHT, CAPTCHA_WIDTH
#Picture to black and white, 3D to 1D
convert2Gray = lambda img: np.mean(img, -1) if len(img.shape) > 2 else img
#Convert verification code vector to text
vec2Text = lambda vec, captcha_list=CAPTCHA_LIST: ''.join([captcha_list[int(v)] for v in vec])
def text2Vec(text, captchaLen=CAPTCHA_LEN, captchaList=CAPTCHA_LIST):
    """
    Convert verification code text to vector
    """
    vector = np.zeros(captchaLen * len(captchaList))
    for i in range(len(text)):
        vector[captchaList.index(text[i]) + i * len(captchaList)] = 1
    return vector
def getNextBatch(batchCount=60, width=CAPTCHA_WIDTH, height=CAPTCHA_HEIGHT):
    """
    Get training picture group
    """
    batchX = np.zeros([batchCount, width * height])
    batchY = np.zeros([batchCount, CAPTCHA_LEN * len(CAPTCHA_LIST)])
    for i in range(batchCount):
        text, image = genCaptchaTextImage()
        image = convert2Gray(image)
        #The image array is one-dimensional, and the text is also corresponding to the same line of two-dimensional groups
        batchX[i, :] = image.flatten() / 255
        batchY[i, :] = text2Vec(text)
    return batchX, batchY
# print(getNextBatch(batch_count=1))

model_ The train.py file is mainly used for model training. In this file, the basic information of the model is defined. For example, the model is a three-layer convolutional neural network, and the original image size is 60160, becomes 60 after the first convolution160, after the first pool, it becomes 3080; It becomes 30 after the second convolution80, changed to 15 after the second pool40; After the third convolution, it becomes   fifteen40, changed to 7 after the third pool20。 After three times of convolution and pooling, the original picture data becomes 7At the same time, during the training of the project, the data test shall be conducted every 100 times to calculate the accuracy:

# -*- coding:utf-8 -*-
import tensorflow.compat.v1 as tf
from datetime import datetime
from util import getNextBatch
from captcha_gen import CAPTCHA_HEIGHT, CAPTCHA_WIDTH, CAPTCHA_LEN, CAPTCHA_LIST
tf.compat.v1.disable_eager_execution()
variable = lambda shape, alpha=0.01: tf.Variable(alpha * tf.random_normal(shape))
conv2d = lambda x, w: tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding='SAME')
maxPool2x2 = lambda x: tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
optimizeGraph = lambda y, y_conv: tf.train.AdamOptimizer(1e-3).minimize(
    tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=y, logits=y_conv)))
hDrop = lambda image, weight, bias, keepProb: tf.nn.dropout(
    maxPool2x2(tf.nn.relu(conv2d(image, variable(weight, 0.01)) + variable(bias, 0.1))), keepProb)
def cnnGraph(x, keepProb, size, captchaList=CAPTCHA_LIST, captchaLen=CAPTCHA_LEN):
    """
    Three layer convolutional neural network
    """
    imageHeight, imageWidth = size
    xImage = tf.reshape(x, shape=[-1, imageHeight, imageWidth, 1])
    hDrop1 = hDrop(xImage, [3, 3, 1, 32], [32], keepProb)
    hDrop2 = hDrop(hDrop1, [3, 3, 32, 64], [64], keepProb)
    hDrop3 = hDrop(hDrop2, [3, 3, 64, 64], [64], keepProb)
    #Full connection layer
    imageHeight = int(hDrop3.shape[1])
    imageWidth = int(hDrop3.shape[2])
    WFC = variable ([imageheight * imagewidth * 64, 1024], 0.01) # there are 64 neurons in the upper layer and 1024 neurons in the whole connection layer
    bFc = variable([1024], 0.1)
    hDrop3Re = tf.reshape(hDrop3, [-1, imageHeight * imageWidth * 64])
    hFc = tf.nn.relu(tf.matmul(hDrop3Re, wFc) + bFc)
    hDropFc = tf.nn.dropout(hFc, keepProb)
    #Output layer
    wOut = variable([1024, len(captchaList) * captchaLen], 0.01)
    bOut = variable([len(captchaList) * captchaLen], 0.1)
    yConv = tf.matmul(hDropFc, wOut) + bOut
    return yConv
def accuracyGraph(y, yConv, width=len(CAPTCHA_LIST), height=CAPTCHA_LEN):
    """
    Deviation calculation chart, correct value and predicted value, calculation accuracy
    """
    maxPredictIdx = tf.argmax(tf.reshape(yConv, [-1, height, width]), 2)
    maxLabelIdx = tf.argmax(tf.reshape(y, [-1, height, width]), 2)
    Correct = tf.equal (maxpredictidx, maxlabelidx) # judge whether it is equal
    return tf.reduce_mean(tf.cast(correct, tf.float32))
def train(height=CAPTCHA_HEIGHT, width=CAPTCHA_WIDTH, ySize=len(CAPTCHA_LIST) * CAPTCHA_LEN):
    """
    CNN training
    """
    accRate = 0.95
    x = tf.placeholder(tf.float32, [None, height * width])
    y = tf.placeholder(tf.float32, [None, ySize])
    keepProb = tf.placeholder(tf.float32)
    yConv = cnnGraph(x, keepProb, (height, width))
    optimizer = optimizeGraph(y, yConv)
    accuracy = accuracyGraph(y, yConv)
    saver = tf.train.Saver()
    with tf.Session() as sess:
        Sess.run (TF. Global_variables_initializer()) # initialization
        Step = 0 # steps
        while True:
            batchX, batchY = getNextBatch(64)
            sess.run(optimizer, feed_dict={x: batchX, y: batchY, keepProb: 0.75})
            #Test every 100 times of training
            if step % 100 == 0:
                batchXTest, batchYTest = getNextBatch(100)
                acc = sess.run(accuracy, feed_dict={x: batchXTest, y: batchYTest, keepProb: 1.0})
                print(datetime.now().strftime('%c'), ' step:', step, ' accuracy:', acc)
                #The accuracy meets the requirements and the model is saved
                if acc > accRate:
                    modelPath = "./model/captcha.model"
                    saver.save(sess, modelPath, global_step=step)
                    accRate += 0.01
                    if accRate > 0.90:
                        break
            step = step + 1
train()

After completing this part, we can train the model through the local machine. In order to improve the training speed, I set the accrate part of the code as:

if accRate > 0.90:
    break

In other words, when the accuracy exceeds 90%, the system will automatically stop and save the model.

Next you can train:

How to easily identify the verification code through serverless?

The training time may be long. After the training, you can draw according to the results and view the change curve of accuracy with the increase of step:

How to easily identify the verification code through serverless?

The horizontal axis represents the training step, and the vertical axis represents the accuracy

3. Verification code identification based on serverless architecture

Further integrate the above code parts and code according to the specification of function calculation:

# -*- coding:utf-8 -*-
#Core backend services
import base64
import json
import uuid
import tensorflow as tf
import random
import numpy as np
from PIL import Image
from captcha.image import ImageCaptcha
# Response
class Response:
    def __init__(self, start_response, response, errorCode=None):
        self.start = start_response
        responseBody = {
            'Error': {"Code": errorCode, "Message": response},
        } if errorCode else {
            'Response': response
        }
        #UUID is added by default to facilitate later positioning
        responseBody['ResponseId'] = str(uuid.uuid1())
        print("Response: ", json.dumps(responseBody))
        self.response = json.dumps(responseBody)
    def __iter__(self):
        status = '200'
        response_headers = [('Content-type', 'application/json; charset=UTF-8')]
        self.start(status, response_headers)
        yield self.response.encode("utf-8")
CAPTCHA_LIST = [eve for eve in "0123456789abcdefghijklmnopqrsruvwxyzABCDEFGHIJKLMOPQRSTUVWXYZ"]
CAPTCHA_ Len = 4 # verification code length
CAPTCHA_ Height = 60 # verification code height
CAPTCHA_ Width = 160 # verification code width
#Random string
randomStr = lambda num=5: "".join(random.sample('abcdefghijklmnopqrstuvwxyz', num))
randomCaptchaText = lambda char=CAPTCHA_LIST, size=CAPTCHA_LEN: "".join([random.choice(char) for _ in range(size)])
#Picture to black and white, 3D to 1D
convert2Gray = lambda img: np.mean(img, -1) if len(img.shape) > 2 else img
#Convert verification code vector to text
vec2Text = lambda vec, captcha_list=CAPTCHA_LIST: ''.join([captcha_list[int(v)] for v in vec])
variable = lambda shape, alpha=0.01: tf.Variable(alpha * tf.random_normal(shape))
conv2d = lambda x, w: tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding='SAME')
maxPool2x2 = lambda x: tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
optimizeGraph = lambda y, y_conv: tf.train.AdamOptimizer(1e-3).minimize(
    tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=y, logits=y_conv)))
hDrop = lambda image, weight, bias, keepProb: tf.nn.dropout(
    maxPool2x2(tf.nn.relu(conv2d(image, variable(weight, 0.01)) + variable(bias, 0.1))), keepProb)
def genCaptchaTextImage(width=CAPTCHA_WIDTH, height=CAPTCHA_HEIGHT, save=None):
    image = ImageCaptcha(width=width, height=height)
    captchaText = randomCaptchaText()
    if save:
        image.write(captchaText, save)
    return captchaText, np.array(Image.open(image.generate(captchaText)))
def text2Vec(text, captcha_len=CAPTCHA_LEN, captcha_list=CAPTCHA_LIST):
    """
    Convert verification code text to vector
    """
    vector = np.zeros(captcha_len * len(captcha_list))
    for i in range(len(text)):
        vector[captcha_list.index(text[i]) + i * len(captcha_list)] = 1
    return vector
def getNextBatch(batch_count=60, width=CAPTCHA_WIDTH, height=CAPTCHA_HEIGHT):
    """
    Get training picture group
    """
    batch_x = np.zeros([batch_count, width * height])
    batch_y = np.zeros([batch_count, CAPTCHA_LEN * len(CAPTCHA_LIST)])
    for i in range(batch_count):
        text, image = genCaptchaTextImage()
        image = convert2Gray(image)
        #The image array is one-dimensional, and the text is also corresponding to the same line of two-dimensional groups
        batch_x[i, :] = image.flatten() / 255
        batch_y[i, :] = text2Vec(text)
    return batch_x, batch_y
def cnnGraph(x, keepProb, size, captchaList=CAPTCHA_LIST, captchaLen=CAPTCHA_LEN):
    """
    Three layer convolutional neural network
    """
    imageHeight, imageWidth = size
    xImage = tf.reshape(x, shape=[-1, imageHeight, imageWidth, 1])
    hDrop1 = hDrop(xImage, [3, 3, 1, 32], [32], keepProb)
    hDrop2 = hDrop(hDrop1, [3, 3, 32, 64], [64], keepProb)
    hDrop3 = hDrop(hDrop2, [3, 3, 64, 64], [64], keepProb)
    #Full connection layer
    imageHeight = int(hDrop3.shape[1])
    imageWidth = int(hDrop3.shape[2])
    WFC = variable ([imageheight * imagewidth * 64, 1024], 0.01) # there are 64 neurons in the upper layer and 1024 neurons in the whole connection layer
    bFc = variable([1024], 0.1)
    hDrop3Re = tf.reshape(hDrop3, [-1, imageHeight * imageWidth * 64])
    hFc = tf.nn.relu(tf.matmul(hDrop3Re, wFc) + bFc)
    hDropFc = tf.nn.dropout(hFc, keepProb)
    #Output layer
    wOut = variable([1024, len(captchaList) * captchaLen], 0.01)
    bOut = variable([len(captchaList) * captchaLen], 0.1)
    yConv = tf.matmul(hDropFc, wOut) + bOut
    return yConv
def captcha2Text(image_list):
    """
    Convert captcha image to text
    """
    with tf.Session() as sess:
        saver.restore(sess, tf.train.latest_checkpoint('model/'))
        predict = tf.argmax(tf.reshape(yConv, [-1, CAPTCHA_LEN, len(CAPTCHA_LIST)]), 2)
        vector_list = sess.run(predict, feed_dict={x: image_list, keepProb: 1})
        vector_list = vector_list.tolist()
        text_list = [vec2Text(vector) for vector in vector_list]
        return text_list
x = tf.placeholder(tf.float32, [None, CAPTCHA_HEIGHT * CAPTCHA_WIDTH])
keepProb = tf.placeholder(tf.float32)
yConv = cnnGraph(x, keepProb, (CAPTCHA_HEIGHT, CAPTCHA_WIDTH))
saver = tf.train.Saver()
def handler(environ, start_response):
    try:
        request_body_size = int(environ.get('CONTENT_LENGTH', 0))
    except (ValueError):
        request_body_size = 0
    requestBody = json.loads(environ['wsgi.input'].read(request_body_size).decode("utf-8"))
    imageName = randomStr(10)
    imagePath = "/tmp/" + imageName
    print("requestBody: ", requestBody)
    reqType = requestBody.get("type", None)
    if reqType == "get_captcha":
        genCaptchaTextImage(save=imagePath)
        with open(imagePath, 'rb') as f:
            data = base64.b64encode(f.read()).decode()
        return Response(start_response, {'image': data})
    if reqType == "get_text":
        #Image acquisition
        print("Get pucture")
        imageData = base64.b64decode(requestBody["image"])
        with open(imagePath, 'wb') as f:
            f.write(imageData)
        #Start prediction
        img = Image.open(imageName)
        img = img.resize((160, 60), Image.ANTIALIAS)
        img = img.convert("RGB")
        img = np.asarray(img)
        image = convert2Gray(img)
        image = image.flatten() / 255
        return Response(start_response, {'result': captcha2Text([image])})

This function mainly includes two interfaces:

• obtain the verification code: the user tests and generates the verification code
• obtain verification code identification results: user identification, use and identification verification code

For this part of the code, the required dependencies are as follows:

tensorflow==1.13.1
numpy==1.19.4
scipy==1.5.4
pillow==8.0.1
captcha==0.3

In addition, for a simpler experience, a test page is provided. The background service of the test page uses the python web bolt framework:

# -*- coding:utf-8 -*-
import os
import json
from bottle import route, run, static_file, request
import urllib.request
url = "http://" + os.environ.get("url")
@route('/')
def index():
    return static_file("index.html", root='html/')
@route('/get_captcha')
def getCaptcha():
    data = json.dumps({"type": "get_captcha"}).encode("utf-8")
    reqAttr = urllib.request.Request(data=data, url=url)
    return urllib.request.urlopen(reqAttr).read().decode("utf-8")
@route('/get_captcha_result', method='POST')
def getCaptcha():
    data = json.dumps({"type": "get_text", "image": json.loads(request.body.read().decode("utf-8"))["image"]}).encode(
        "utf-8")
    reqAttr = urllib.request.Request(data=data, url=url)
    return urllib.request.urlopen(reqAttr).read().decode("utf-8")
run(host='0.0.0.0', debug=False, port=9000)

The back-end service depends on:

bottle==0.12.19

Front end page code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    < title > verification code identification test system < / Title >
    <link href="https://www.bootcss.com/p/layoutit/css/bootstrap-combined.min.css" rel="stylesheet">
    <script>
        var image = undefined
        function getCaptcha() {
            const xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
            xmlhttp.open("GET", '/get_captcha', false);
            xmlhttp.onreadystatechange = function () {
                if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                    image = JSON.parse(xmlhttp.responseText).Response.image
                    document.getElementById("captcha").src = "data:image/png;base64," + image
                    document.getElementById("getResult").style.visibility = 'visible'
                }
            }
            xmlhttp.setRequestHeader("Content-type", "application/json");
            xmlhttp.send();
        }
        function getCaptchaResult() {
            const xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
            xmlhttp.open("POST", '/get_captcha_result', false);
            xmlhttp.onreadystatechange = function () {
                if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                    Document. Getelementbyid ("result"). InnerText = "recognition result:" + json.parse (xmlhttp. ResponseText). Response.result
                }
            }
            xmlhttp.setRequestHeader("Content-type", "application/json");
            xmlhttp.send(JSON.stringify({"image": image}));
        }
    </script>
</head>
<body>
<div class="container-fluid" style="margin-top: 10px">
    <div class="row-fluid">
        <div class="span12">
            <center>
                <h3>
                    Verification code identification test system
                </h3>
            </center>
        </div>
    </div>
    <div class="row-fluid">
        <div class="span2">
        </div>
        <div class="span8">
            <center>
                <img id="captcha"/>
                <br><br>
                <p id="result"></p>
            </center>
            <fieldset>
                < legend > operation: < / legend >
                < button class = "BTN" onclick = "getcaptcha()" > get verification code < / button >
                < button class = "BTN" onclick = "getcaptcharesult()" id = "getResult" style = "visibility: hidden" > identification verification code
                </button>
            </fieldset>
        </div>
        <div class="span2">
        </div>
    </div>
</div>
</body>
</html>

Once the code is ready, start writing the deployment file:

Global:
  Service:
      Name: ServerlessBook
      Description: serverless book case
      Log: Auto
      Nas: Auto
ServerlessBookCaptchaDemo:
  Component: fc
  Provider: alibaba
  Access: release
  Extends:
    deploy:
      - Hook: s install docker
        Path: ./
        Pre: true
  Properties:
    Region: cn-beijing
    Service: ${Global.Service}
    Function:
      Name: serverless_captcha
      Description: verification code identification
      CodeUri:
        Src: ./src/backend
        Excludes:
          - src/backend/.fun
          - src/backend/model
      Handler: index.handler
      Environment:
        - Key: PYTHONUSERBASE
          Value: /mnt/auto/.fun/python
      MemorySize: 3072
      Runtime: python3
      Timeout: 60
      Triggers:
        - Name: ImageAI
          Type: HTTP
          Parameters:
            AuthType: ANONYMOUS
            Methods:
              - GET
              - POST
              - PUT
            Domains:
              - Domain: Auto
ServerlessBookCaptchaWebsiteDemo:
  Component: bottle
  Provider: alibaba
  Access: release
  Extends:
    deploy:
      - Hook: pip3 install -r requirements.txt -t ./
        Path: ./src/website
        Pre: true
  Properties:
    Region: cn-beijing
    CodeUri: ./src/website
    App: index.py
    Environment:
      - Key: url
        Value: ${ServerlessBookCaptchaDemo.Output.Triggers[0].Domains[0]}
    Detail:
      Service: ${Global.Service}
      Function:
        Name: serverless_captcha_website

Overall directory structure:

|- SRC # project directory
 || - backend # project backend, core interface
 || - index.py # backend core code
 || - requirements.txt # backend core code dependency
 || - front end of website # project, easy to test and use
 || - HTML # project front page
 || - index.html # project front page
 || - index.py # project front-end background service (bottle framework)
 || - requirements.txt # project front-end background service dependency

After completion, we can deploy the project in the project directory:

s deploy

After deployment, open the returned page address:

How to easily identify the verification code through serverless?

Click get verification code to generate a verification code online:

How to easily identify the verification code through serverless?

Click the identification verification code to identify the verification code:

How to easily identify the verification code through serverless?

Since the target accuracy rate of the model is 90% during training, it can be considered that the overall accuracy rate is about 90% after the massive same type verification code test.

summary

Serverless is developing rapidly. I think it’s a very cool thing to make a verification code identification tool through serverless. In the future work of data acquisition, it is very necessary to have a beautiful verification code recognition tool. Of course, there are many kinds of verification codes. For different types of verification codes, it is also a very challenging work.