自动登录——使用 CNN 识别验证码

代码位于 https://github.com/airstone42/daka 。
CNN
上图中的是目标网站的验证码。
由于一些原因,需要写一个每日自动登录并执行相关操作的脚本,但被这个验证码拦住了。因此,若需要正常的 HTTP 自动访问就需要过验证码这一关。
幸而在他人的帮助下,得知了这个目标网站所使用的原型。从这里可以得知,其使用的 Java 验证码库为 cage。目标网站对原型做了修改,只使用了两位数字作为验证码。
因此,可以简单地对验证码做如下操作:
- 请求网址,获取二进制 PNG 图片
- 读取图片宽度,对半平分
- 两边各自训练模型,均为十分类器,目标为数字
- 分别识别,合并结果,并与记录的 cookie 和 token 一并提交
首先,需要得到数据集,好在已经得知验证码库,因此可以自动构造。
针对图像数据,CNN 是一个常用的神经网络模型,这里使用了入手较为简单的 Keras,并以 TensorFlow 为后端,参考 Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow: Concepts, Tools, and Techniques to Build Intelligent Systems 2nd Edition 第 14 章,代码页面在此。
from functools import partial DefaultConv2D = partial(keras.layers.Conv2D, kernel_size=3, activation='relu', padding="SAME") model = keras.models.Sequential([ DefaultConv2D(filters=64, kernel_size=7, input_shape=[28, 28, 1]), keras.layers.MaxPooling2D(pool_size=2), DefaultConv2D(filters=128), DefaultConv2D(filters=128), keras.layers.MaxPooling2D(pool_size=2), DefaultConv2D(filters=256), DefaultConv2D(filters=256), keras.layers.MaxPooling2D(pool_size=2), keras.layers.Flatten(), keras.layers.Dense(units=128, activation='relu'), keras.layers.Dropout(0.5), keras.layers.Dense(units=64, activation='relu'), keras.layers.Dropout(0.5), keras.layers.Dense(units=10, activation='softmax'), ])
实际使用中修改了上述代码中的部分数据。针对生成的 30000 张训练集,左半侧的准确率为 99.816668%,右半侧为 99.233335%。
可见,在直接对半平分的情况下,尽管左右侧数字并不完整,但有着大量的数据及合适的模型,分类器的准确率依然很高。
自动登录脚本
这部分比较常规,使用的是 Python 的 Requests 库和 BeautifulSoup4 库,没什么特别的内容。
值得记录的一点是,Requests 库默认情况下针对 HTTP 302 的请求会自动跳转,并将跳转前的内容记录在 requests.Response 的 history 字段中。当前的 Response 对象的 url 字段为跳转后的 URL。