python识别验证码的思路及解决方案

1. 前言

验证码是用来区分人类和机器的一种认证机制,但是随着机器学习技术的发展,许多机器都可以伪造人类的行为模式,为了进一步区分人类和机器,验证码的制作变得越来越复杂。但是,对于爬虫等特定场景下的验证码破解,机器学习的方法受到了很大的限制,因此,python识别验证码,成为了不少从事网络爬虫的人的必需技能。

2. 验证码识别的方法

2.1 传统的验证码识别方法

传统的验证码识别方法包括前端校验、简单数字字母组合等。这种类型的验证码可以通过图像处理,特征提取,字符识别等方法进行识别。

图像处理:将图片中的噪声去除;

特征提取:将图片中的字符转化为可分类的特征;

字符识别:将提取的字符特征通过机器学习算法进行训练分类;

这种方法的精度比较高,但是对于国内的主流验证码,如中文,繁体中文或是斜体验证码,会存在一定的局限性。

2.2 机器学习方法

机器学习识别验证码可以分为两步:先训练再识别。训练过程需要先收集样本,并通过图像处理和特征提取将图像转化为向量,然后通过神经网络对向量进行训练,训练出分类器;识别过程,将未知的验证码图像转化为向量,然后通过训练好的分类器对其进行判断,得到识别的结果。

采用机器学习技术识别验证码,相比于传统的识别方法,有更高的识别精度,但是需要大量的样本训练,并且需要选择合适的特征提取方法和神经网络模型,否则就可能造成过拟合或是欠拟合等问题。

3. python识别验证码的方法

3.1 图像处理

验证码识别的第一步就是对验证码图片进行处理,使其更加易于识别。

在python中,可以使用PIL库进行图像处理。

from PIL import Image

# 读取图片

image = Image.open('captcha-image.png')

# 将图片转化为灰度图像

image = image.convert('L')

# 将图片转化为黑白二值图像

threshold = 200

table = []

for i in range(256):

if i < threshold:

table.append(0)

else:

table.append(1)

image = image.point(table, '1')

上述代码中使用了三个方法:convert(), point()和open()。其中,convert()方法将图片转化为灰度图像;point()方法将图片转化为黑白二值图像,这可以有效去除图片中的噪点;open()方法是用来读取图片的。

3.2 特征提取

特征提取就是将图片中的字符转化为可分类的特征,一般采用图像的形态和轮廓等来进行提取

在python中,可以使用opencv-python库进行特征提取。

import cv2

# 加载图片

img = cv2.imread('captcha-image.png', cv2.IMREAD_GRAYSCALE)

# 二值化处理

(thresh, img_bw) = cv2.threshold(img, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

# 查找轮廓

contours, hierarchy = cv2.findContours(img_bw, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 获取图像特征

features = []

for i in range(len(contours)):

x, y, w, h = cv2.boundingRect(contours[i])

features.append([x, y, w, h])

# 输出特征

print(features)

上述代码中使用了三个方法:imread(), threshold()和findContours()。其中,imread()方法用于加载图片;threshold()方法用于将图片二值化;findContours()方法用于查找图像中的轮廓。

特征提取的结果就是图片中每个字符的位置和大小,保存在features列表中,可以用于后续的识别。

3.3 训练模型和识别

训练模型和识别是验证码识别的核心,python中可以使用tensorflow、keras、pytorch等库来实现。

下面给出一个使用keras库的实例代码:

from keras.models import Sequential

from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPool2D

from keras.optimizers import RMSprop

import numpy as np

# 读取样本

x_train = np.load('captcha_images.npy')

y_train = np.load('captcha_labels.npy')

# 定义模型

model = Sequential()

model.add(Conv2D(filters=32, kernel_size=(5, 5), padding='Same', activation='relu', input_shape=(28, 28, 1)))

model.add(Conv2D(filters=32, kernel_size=(5, 5), padding='Same', activation='relu'))

model.add(MaxPool2D(pool_size=(2, 2)))

model.add(Dropout(0.25))

model.add(Conv2D(filters=64, kernel_size=(3, 3), padding='Same', activation='relu'))

model.add(Conv2D(filters=64, kernel_size=(3, 3), padding='Same', activation='relu'))

model.add(MaxPool2D(pool_size=(2, 2), strides=(2, 2)))

model.add(Dropout(0.25))

model.add(Flatten())

model.add(Dense(256, activation='relu'))

model.add(Dropout(0.5))

model.add(Dense(10, activation='softmax'))

# 设置优化器

optimizer = RMSprop(lr=0.001, rho=0.9, epsilon=1e-08, decay=0.0)

# 编译模型

model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])

# 训练模型

model.fit(x_train, y_train, epochs=10, batch_size=86)

上述代码中,首先需要读取样本,然后定义模型,并设置优化器,接着编译模型,并进行训练。这里使用了CNN神经网络模型(卷积神经网络),同样,也可以使用其他的模型进行训练。

训练完毕之后,可以使用模型进行验证码的识别。

# 加载模型

from keras.models import load_model

model = load_model('captcha_model.h5')

# 验证码识别

img = cv2.imread('captcha-image.png', cv2.IMREAD_GRAYSCALE)

img = cv2.resize(img, (28, 28))

img = np.array(img, dtype=np.float32)

img = np.reshape(img, (-1, 28, 28, 1))

img /= 255

predict = model.predict(img)

result = np.argmax(predict[0])

print(result)

上述代码中,调用keras.models库中的load_model()方法加载模型,然后对待识别的验证码进行处理,最后对其进行识别,输出识别的结果。

4. 结论

验证码识别是网络爬虫必备的技能之一。我们可以使用传统的图像处理和特征提取方法,也可以使用机器学习的方法。python是一个强大的语言,可以通过PIL、opencv-python、keras等库来完成验证码的识别任务。

后端开发标签