Tensorflow实战(二):Discuz验证码识别

2018年1月29日09:04:20 221 22,521 °C
摘要

本文将使用深度学习框架Tensorflow训练出一个用于破解Discuz验证码的模型。

Tensorflow实战(二):Discuz验证码识别

一、前言

验证码是根据随机字符生成一幅图片,然后在图片中加入干扰象素,用户必须手动填入,防止有人利用机器人自动批量注册、灌水、发垃圾广告等等 。

验证码的作用是验证用户是真人还是机器人。

本文将使用深度学习框架Tensorflow训练出一个用于破解Discuz验证码的模型。

自动生成验证码接口关闭,原因如下:

Tensorflow实战(二):Discuz验证码识别

接口是用来方便大家获取验证码图片的,已经声明至少加200ms延时,但是有些人就是不管不顾,个人网站带宽不大,直接被占满(自己写代码让别人爬自己网站真是找罪受),服务器被蹂躏十多分钟。这种情况已经出现很多次了,实在受不了,只能关闭此功能,望谅解了。

想要Discuz验证码生成代码(php)的,到网盘下载吧(密码:nf1t):

二、背景介绍

我们先看下简单的Discuz验证码。

Tensorflow实战(二):Discuz验证码识别

打开下面的连接,你就可以看到这个验证码了。

https://cuijiahua.com/tutrial/discuz/index.php?label=jack

怎么获取其他验证码呢?我已经为大家准备好了api,格式如下:

观察上述链接,你会发现label后面跟着的就是要显示的图片字母,改变label后面的值,我们就可以获得不同的Discuz验证码图片。

如果会网络爬虫,我想根据这个api获取Discuz验证码图片对你来说应该很Easy。

不会网络爬虫也没有关系,爬虫代码我已经为你准备好了。创建一个get_discuz.py文件,添加如下代码:

运行上述代码,你就可以下载5000张Discuz验证码图片到本地,但是要注意的一点是:请至少加200ms延时,避免给我的服务器造成过多的压力,如发现影响服务器正常工作,我会关闭此功能。

你好我也好,大家好才是真的好!

验证码下载过程如下图所示:

Tensorflow实战(二):Discuz验证码识别

当然,如果你想省略麻烦的下载步骤也是可以的,我已经为大家准备好了6万张的Discuz验证码图片。我想应该够用了吧,如果感觉不够用,可以自行使用爬虫程序下载更多的验证码。

6万张的Discuz验证码图片可到文章末尾处下载。

准备好的数据集,它们都是100*30大小的图片:

Tensorflow实战(二):Discuz验证码识别

什么?你说这个图片识别太简单?没关系,有高难度的!

点我查看,认出是什么字母算我输!

我打开的图片如下所示:

Tensorflow实战(二):Discuz验证码识别

这是一个动图,并且还带倾斜、扭曲等特效。怎么通过api获得这种图片呢?

没错,只要添加一些参数就可以了,格式如上图所示,每个参数的说明如下:

  • label:验证码
  • width:验证码宽度
  • height:验证码高度
  • background:是否随机图片背景
  • adulterate:是否随机背景图形
  • ttf:是否随机使用ttf字体
  • angle:是否随机倾斜度
  • warping:是否随机扭曲
  • scatter:是否图片打散
  • color:是否随机颜色
  • size:是否随机大小
  • shadow:是否文字阴影
  • animator:是否GIF动画

你可以根据你的喜好,定制你想要的验证码图片。

个人感觉,下面这样的动图还是不错的:

Tensorflow实战(二):Discuz验证码识别

不过,为了简单起见,我们只使用最简单的验证码图片进行验证码识别。

数据集已经准备好,那么接下来进入本文的重点,Tensorflow实战。

三、Discuz验证码识别

我们已经将验证码下载好,并且文件名就是对应图片的标签。这里需要注意的是:我们忽略了图片中英文的大小写。

1、数据预处理

首先,数据预处理分为两个部分,第一部分是读取图片,并划分训练集和测试集。因为整个数据集为6W张图片,所以我们可以让训练集为5W张,测试集为1W张。随后,虽然标签是文件名,我们认识,但是机器是不认识的,因此我们要使用text2vec,将标签进行向量化。

明确了目的,那开始实践吧!

读取数据:

我们通过定义rate,来确定划分比例。例如:测试集1W张,训练集5W张,那么rate=1W/5W=0.2。

标签向量化:

既然需要将标签向量化,那么,我们也需要将向量化的标签还原回来。

运行上述测试代码,你会发现,文本向量化竟如此简单:Tensorflow实战(二):Discuz验证码识别

这里我们包括了63个字符的转化,0-9 a-z A-Z _(验证码如果小于4,用_补齐)。

2、根据batch_size获取数据

我们在训练模型的时候,需要根据不同的batch_size"喂"数据。这就需要我们写个函数,从整体数据集中获取指定batch_size大小的数据。

上述代码无法运行,这是我封装到类里的函数,整体代码会在文末放出。现在理解下这段代码,我们通过train_flag来确定是从训练集获取数据还是测试集获取数据,通过batch_size来获取指定大小的数据。获取数据之后,将batch_size大小的图片数据和经过向量化处理的标签存放到numpy数组中。

3、CNN模型

网络模型如下:

3卷积层+1全链接层。

继续看下我封装到类里的函数:

为了省事,name_scope什么都没有设定。每个网络层的功能,维度都已经在注释里写清楚了,甚至包括tensorflow相应函数的说明也注释好了。

如果对于网络结构计算不太了解,推荐看下LeNet-5网络解析:

https://cuijiahua.com/blog/2018/01/dl_3.html

LeNet-5的网络结构研究清楚了,这里也就懂了。

4、训练函数

准备工作都做好了,我们就可以开始训练了。

上述代码依旧是我封装到类里的函数,与我的上篇文章《Tensorflow实战(一):打响深度学习的第一枪 – 手写数字识别(Tensorboard可视化)》重复的内容不再讲解,包括Tensorboard的使用方法。

这里需要强调的一点是,我们需要在迭代到500次的时候重新获取下数据集,这样做其实就是打乱了一次数据集。为什么要打乱数据集呢?因为如果不打乱数据集,在训练的时候,Tensorboard绘图会有如下现象:

Tensorflow实战(二):Discuz验证码识别

可以看到,准确率曲线和Loss曲线存在跳变,这就是因为我们没有在迭代一定次数之后打乱数据集造成的。

同时,虽然我定义了dropout层,但是在训练的时候没有使用它,所以才把dropout值设置为1。

5、整体训练代码

指定GPU,指定Tensorboard数据存储路径,指定最大迭代次数,跟Tensorflow实战(一)的思想都是一致的。这里,设置最大迭代次数为100W次。

我使用的GPU是Titan X,如果是使用CPU训练估计会好几天吧....

创建train.py文件,添加如下代码:

代码跑了一个多小时终于跑完了,Tensorboard显示的数据:

Tensorflow实战(二):Discuz验证码识别

准确率达到百分之90以上吧。

6、测试代码

已经有训练好的模型了,怎么加载已经训练好的模型进行预测呢?在和train.py相同目录下,创建test.py文件,添加如下代码:

运行程序,随机从测试集挑选5张图片,效果还行,错了一个字母:

Tensorflow实战(二):Discuz验证码识别

四、总结

  • 通过修改网络结构,以及超参数,学习如何调参。
  • 可以试试其他的网络结构,准确率还可以提高很多的。
  • Discuz验证码可以使用更复杂的,这仅仅是个小demo。
  • 如有问题,请留言。如有错误,还望指正,谢谢!

 

PS: 如果觉得本篇本章对您有所帮助,欢迎关注、评论、赞!

本文出现的所有代码和数据集,均可在我的github上下载,欢迎Follow、Star:点击查看

文件下载 Discuz验证码
下载地址
weinxin
微信公众号
分享技术,乐享生活:微信公众号搜索「JackCui-AI」关注一个在互联网摸爬滚打的潜行者。
求知若饥,虚心若愚。--- 乔布斯
Jack Cui

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

目前评论:221   其中:访客  127   博主  94

    • avatar HeyMan 来自天朝的朋友 搜狗浏览器 Windows 10 广东省深圳市宝安区 电信 1

      大佬你好,我是你的忠实fans

        • avatar Jack Cui Admin 来自天朝的朋友 谷歌浏览器 Windows 7 辽宁省沈阳市 东北大学四舍(女生)

          @HeyMan 哈哈,感谢支持~

            • avatar HeyMan 来自天朝的朋友 搜狗浏览器 Windows 10 广东省深圳市宝安区 电信 1

              @Jack Cui 我觉得学机器学习看你的教程就够了,不仅通俗易懂还时常更新加上代码实战检验,最最最主要的是还有真人随时解答。啊哈哈

                • avatar Jack Cui Admin 来自天朝的朋友 谷歌浏览器 Windows 7 辽宁省沈阳市 东北大学四舍(女生)

                  @HeyMan 哈哈,继续一起加油 :idea:

            • avatar 卷卷 来自天朝的朋友 谷歌浏览器 Windows 10 辽宁省沈阳市 联通 3

              好赞呀~棒棒哒~

              • avatar 2495332611 来自天朝的朋友 搜狗浏览器 Windows 10 云南省昆明市 电信 2

                File “E:/untitled1/Discuz/train.py”, line 367, in
                dz.train_crack_captcha_cnn()
                File “E:/untitled1/Discuz/train.py”, line 338, in train_crack_captcha_cnn
                batch_x_test, batch_y_test = self.get_next_batch(False, 100)
                IndexError: tuple index out of range
                博主,Windows运行您的代码train.py出现以上错误,希望能解答

                  • avatar Jack Cui Admin 来自天朝的朋友 谷歌浏览器 Windows 7 辽宁省沈阳市 东北大学四舍(女生)

                    @2495332611 你下载数据集了吗?

                      • avatar 2495332611 来自天朝的朋友 搜狗浏览器 Windows 10 云南省昆明市 电信 2

                        @Jack Cui 嗯,我是用你的爬虫爬的6000张图片作为数据集的

                          • avatar Jack Cui Admin 来自天朝的朋友 谷歌浏览器 Windows 7 辽宁省沈阳市 东北大学四舍(女生)

                            @2495332611 你这个应该是加载的数据有问题,你试试单独调用get_next_batch函数,看看加载的数据是否有问题。分析下是不是路径问题。

                          • avatar 2495332611 来自天朝的朋友 搜狗浏览器 Windows 10 云南省昆明市 电信 2

                            @Jack Cui 不好意思,是我路径的问题,但现在运行又出了一个问题:
                            The TensorFlow library wasn’t compiled to use SSE4.1 instructions, but these are available on your machine and could speed up CPU computations.

                            Process finished with exit code -1073740791 (0xC0000409)
                            它没训练,是我的电脑不支持gpu跑的原因吗,如何改成cpu训练

                              • avatar Jack Cui Admin 来自天朝的朋友 谷歌浏览器 Windows 7 辽宁省沈阳市 东北大学四舍(女生)

                                @2495332611 嗯,这个是因为你没有GPU,去掉GPU的配置项即可。在def __init__函数中。

                                  • avatar 2495332611 来自天朝的朋友 搜狗浏览器 Windows 10 云南省昆明市 电信 2

                                    @Jack Cui def __init__(self):
                                    # 指定GPU
                                    #os.environ[“CUDA_VISIBLE_DEVICES”] = “0”
                                    self.config = tf.ConfigProto(allow_soft_placement = True)
                                    #gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction = 1)
                                    #self.config.gpu_options.allow_growth = True
                                    我注释掉了那几条gpu的配置,但还是不训练,请问还有哪些地方需要改的

                                  • avatar Jack Cui Admin 来自天朝的朋友 谷歌浏览器 Windows 7 辽宁省沈阳市 东北大学四舍(女生)

                                    @2495332611 config也去掉,然后在创建sess中的config也去掉。

                                      • avatar 2495332611 来自天朝的朋友 搜狗浏览器 Windows 10 云南省昆明市 电信 2

                                        @Jack Cui with tf.Session() as sess:
                                        # 写到指定的磁盘路径中
                                        train_writer = tf.summary.FileWriter(self.log_dir + ‘/train’, sess.graph)
                                        之前的config去掉了,然后上面Session()中的config也去掉了,还是不训练,实在很麻烦你了

                                  • avatar Jack Cui Admin 来自天朝的朋友 谷歌浏览器 Windows 7 辽宁省沈阳市 东北大学四舍(女生)

                                    @2495332611 还训练不了?呃,我不知道这回你是哪里报错了啊。根据错误百度下,看自己哪里没有配置好。

                                      • avatar 2495332611 来自天朝的朋友 搜狗浏览器 Windows 10 云南省昆明市 电信 2

                                        @Jack Cui 2018-01-30 16:39:56.282371: W c:\l\tensorflow_1501918863922\work\tensorflow-1.2.1\tensorflow\core\platform\cpu_feature_guard.cc:45] The TensorFlow library wasn’t compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.
                                        2018-01-30 16:39:56.282666: W c:\l\tensorflow_1501918863922\work\tensorflow-1.2.1\tensorflow\core\platform\cpu_feature_guard.cc:45] The TensorFlow library wasn’t compiled to use AVX instructions, but these are available on your machine and could speed up CPU computations.

                                        Process finished with exit code -1073740791 (0xC0000409)
                                        还是这个错误

                                          • avatar Jack Cui Admin 来自天朝的朋友 谷歌浏览器 Windows 7 辽宁省沈阳市 东北大学四舍(女生)

                                            @2495332611 呃,没有读写权限?我没有遇到过这种情况,你搜搜看tf的模型保存,看看按照别人windows下的写法有问题没?

                                          • avatar 2495332611 来自天朝的朋友 搜狗浏览器 Windows 10 云南省昆明市 电信 2

                                            @Jack Cui 谢谢你的耐心回复,剩下的我自己多查查

                                              • avatar Jack Cui Admin 来自天朝的朋友 谷歌浏览器 Windows 7 辽宁省沈阳市 东北大学四舍(女生)

                                                @2495332611 哦,那应该还是cpu那里设置的问题,我没有用过cpu版本的,你百度看看~

                                                  • avatar 2495332611 来自天朝的朋友 搜狗浏览器 Windows 10 云南省昆明市 电信 2

                                                    @Jack Cui 嗯,十分感谢

                                                    • avatar 2495332611 来自天朝的朋友 搜狗浏览器 Windows 10 云南省昆明市 电信 2

                                                      @Jack Cui 代码现在能跑通了,但是最后保存出了问题,网上查了半天也没解决,请您帮我看下
                                                      2018-02-01 09:59:30.409286: … Not found: Failed to create a directory: ; No such file or directory

                                                      ValueError: Parent directory of crack_capcha.model doesn’t exist, can’t save.
                                                      出错的位置应该是这个:saver.save(sess, ‘crack_capcha.model’, global_step=i)
                                                      我改成相对路径saver.save(sess, ‘./crack_capcha.model’, global_step=i)还是不行

                                                    • avatar jcxytt_s 来自天朝的朋友 谷歌浏览器 Windows 7 陕西省西安市 电信 2

                                                      @2495332611 你好,在嘛?你跑的验证码出的IndexError: tuple index out of range 这个训练问题你是如何解决的,还有我也是用windows的cpu跑的,能说下如何进行训练嘛

                                                  • avatar jcxytt_s 来自天朝的朋友 谷歌浏览器 Windows 7 陕西省西安市 电信 2

                                                    @2495332611 在嘛?

                                                    • avatar jcxytt_s 来自天朝的朋友 谷歌浏览器 Windows 7 陕西省西安市 电信 2

                                                      @2495332611 你好,问下你那个路径是怎么处理的

                                                        • avatar Jack Cui Admin 来自天朝的朋友 谷歌浏览器 Windows 7 辽宁省沈阳市 东北大学四舍(女生)

                                                          @jcxytt_s 我都是在同一个目录下,没有路径处理。

                                                      • avatar 差很的真语英我 来自天朝的朋友 火狐浏览器 Ubuntu Linux 贵州省黔南州都匀市 联通 2

                                                        test_show_img 这个转灰度图像的函数 貌似没有用到哦

                                                        • avatar 差很的真语英我 来自天朝的朋友 火狐浏览器 Ubuntu Linux 贵州省黔南州都匀市 联通 2

                                                          test_show_img 这个转灰度图像的函数 貌似没有用到哦,
                                                          所以这个函数其实可以不用写出来 对吗

                                                            • avatar Jack Cui Admin 来自天朝的朋友 谷歌浏览器 Windows 10 黑龙江省哈尔滨市 联通

                                                              @差很的真语英我 这个函数没有用到,就是为了测试用的。看下转换效果。

                                                            • avatar 差很的真语英我 来自天朝的朋友 火狐浏览器 Ubuntu Linux 贵州省黔南州都匀市 联通 2

                                                              get_next_batch函数中,
                                                              img = np.mean(cv2.imread(self.data_path + test), -1)
                                                              请问这个-1代表什么,有什么意义,为什么要加-1

                                                                • avatar Jack Cui Admin 来自天朝的朋友 谷歌浏览器 Windows 10 黑龙江省哈尔滨市 联通

                                                                  @差很的真语英我 numpy的mean函数,这里就是变成灰度图,用我那个没使用的函数 对比下就知道了。

                                                                    • avatar 差很的真语英我 来自天朝的朋友 火狐浏览器 Ubuntu Linux 贵州省黔南州都匀市 联通 2

                                                                      @Jack Cui 谢谢

                                                                  • avatar 差很的真语英我 来自天朝的朋友 火狐浏览器 Ubuntu Linux 贵州省黔南州都匀市 联通 2

                                                                    请问下 如果我想从中自己选一张图片 让他识别出来 该怎么做

                                                                    • avatar 差很的真语英我 来自天朝的朋友 火狐浏览器 Ubuntu Linux 贵州省黔南州都匀市 联通 2

                                                                      刚才问的问题我会了,如果能把测试代码 用文字描述下就更好了,感谢博主

                                                                      • avatar 小青蛙 来自天朝的朋友 谷歌浏览器 Linux 黑龙江省牡丹江市 电信 1

                                                                        你好啊,有一个问题,既然是不分大小写,而且我看生成的label也全是小写的,为啥后面转成vector的时候要加上大写的呢,只用小写把向量维度减小到37个是否能行,另外,如果不考虑’_’这个无法识别的字符的话,把向量化的维度减小到36行不行(0-9和a-z)。

                                                                          • avatar Jack Cui Admin 来自天朝的朋友 谷歌浏览器 Windows 10 黑龙江省哈尔滨市 联通

                                                                            @小青蛙 这个向量化是通用的向量化方法,其实可以较少到0-9和a-z不需要大写即可,为了考虑别人可能用大写,就都写好了

                                                                              • avatar 小青蛙 来自天朝的朋友 谷歌浏览器 Linux 黑龙江省牡丹江市穆棱市 电信 1

                                                                                @Jack Cui 好的,另外还有一个问题,你给的连接里面关于LeNet-5的说明中,指定第一个卷积层是5×5的,然后你这里使用的是3×3的,我想问下这是不是一种使用CNN的技巧呢,对于一些已经验证的网络,只要层使用对了就可以,里面的一些细节和超参数都是可以根据实际情况调整的吗,比如这个验证码的例子,是不是只要网络结构是conv-pool-conv-pool-conv-dense-dense就行,具体里面有多少个卷积核,卷积核的大小这一些都不会影响最后的效果?

                                                                                  • avatar Jack Cui Admin 来自天朝的朋友 谷歌浏览器 Windows 10 黑龙江省哈尔滨市 联通

                                                                                    @小青蛙 这个都是有影响的,具体的东西其实有很多,这个都是参数。推荐看下吴恩达的视频进行了解。

                                                                                      • avatar 小青蛙 来自天朝的朋友 谷歌浏览器 Linux 黑龙江省牡丹江市 电信 1

                                                                                        @Jack Cui 好的,还有我按你的思路自己搭了一个,但是没全抄你的代码,发现在test set上准确率只有60%,我没你训练那么多次,但是到了第20个epoch之后准确率就这样了,也不提高,有什么方法能提升准确率吗,另外,最后你说使用其他网络效果会更好,具体是哪些网络效果会更好呢。

                                                                                      • avatar Jack Cui Admin 来自天朝的朋友 谷歌浏览器 Windows 10 黑龙江省哈尔滨市 联通

                                                                                        @小青蛙 就是一些调参方法了。网络的话,我也没有测试,我就用了这个最简单的网络结构。你可以换个网络试试。

                                                                                  • avatar aaa 来自天朝的朋友 QQ浏览器 Windows 10 上海市 联通 0

                                                                                    hi,问一下,为什么图像你没做灰度处理。还有就是没有做灰度处理,但图像通道你用的是1???

                                                                                      • avatar Jack Cui Admin 来自天朝的朋友 谷歌浏览器  Android 7.1.1 MIX 2 Build/NMF26X 黑龙江省哈尔滨市 联通

                                                                                        @aaa 有做灰度处理,在读取图像的时候就做了。使用np.mean