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等库来完成验证码的识别任务。