如何在html里加入验证码_点选式验证码?使用深度学习搞定它

不点蓝字,我们哪来故事?

汉字点选式验证码解决方案

这是我的第二篇公众号文章add21114e4e645e3b2c140f250529f12.png……

微信公众号不支持Markdown解析,有点难受,正在努力学习排版中eab2e66d6e1920b6e5c5ece9b7c42a5f.png……

这排版可能有点辣眼睛,大佬们凑合着看吧65820ecf14c13c364ee83546d26813f8.png……

相比第一版的排版可能有了一点点进步d690e4062ebb1012319b58ab86369033.png

这是一篇接近三万字的长文,阅读前请做好心理准备0fd0512e07767fc71f95fab0baac4226.png

f3d0c501b778cf937d4059f9adccd9b4.png

方案要点:

  • 点选式验证码的一般解决流程

  • 如何使用xyolo训练自己的目标检测模型

  • 不借助 OCR 功能解决中文验证码的识别问题

4b18857deb084120d1de0860a86b6556.png

爬虫,反爬虫,反反爬虫……一个无限循环。

验证码是反爬虫手段中的常用技术,今天,笔者选择其中的一种——汉字点选式验证码和大家分享一下。

点选式验证码一般会给定两部分内容:

  • 需要点击的几个汉字(为了便于区分,把这部分称为标签部分)。可能直接给文字(可以直接从html中知道是什么字),也可能给一张包含这几个字的图片(从html里面只能获得这张图片,并不知道图片里面是什么字)。

  • 生成的验证码图片(为了便于区分,把这部分称为验证部分)。一般给一张背景图,里面包含多个(大于等于需要点击的汉字个数)被扭曲、加工过的汉字。

要求我们按照汉字给出的顺序,在生成的验证码图片中依次点击正确汉字。下面给个例子:

ceea55fe184f07328b610859548f8b57.png

其中,上方的济拉是给定的、需要点击的文字;下方是被点击区域,包含六个被扭曲、加工过的汉字,我们需要依次正确点击两个字。

是不是感觉挺复杂的样子?莫怕,我们能搞定它!

此项目已经上传到GitHub,你可以直接从GitHub访问源代码和数据集:

https://github.com/AaronJny/captcha_detection

一、方案选择

碰到验证码,解决方法一般可以分成两种:

  • 自己解决它(自己构建模型并训练)

  • 让别人帮我解决它(借助打码平台)

其实并不是什么东西都自己搞才是最好的,合理借助第三方平台或功能同样是个很好的选择。这个需要根据个人的情况做选择,我提供一个参考建议。

什么情况下适合借助打码平台?

  • 验证码触发量小 or 开发周期比较赶 or 不具备独立解决验证码的能力

  • 有打码平台方面的预算

毕竟打码平台真的很便宜,像这种点选式的验证码识别一次才几分钱调用量不大的情况下,成本要比自己动手搞低多了。一是减少了开发成本,二是减少了部署的成本(自己写模型也是要在服务器上部署的)。

打码平台的一般流程:

085e5b0d87a1a7d7174281a13a5407a2.png

具体的打码平台我就不推荐了,没收广告费,大家去网上搜一下就行,有很多。

什么情况下适合自己搞?

  • 调用量很大

  • 打码平台不支持要解决的验证码类型(一般都支持,并且可以协商)

  • 不信任打码平台

  • 业务需求

  • 我不管,我就是要练技术,我就是要自己搞

没有提到的其他情况,还请自行衡量。

不过嘛,今天咱们要讲技术,就不管场景了。我不管,我就是要自己搞!

二、方案架构

2.1 问题拆解

我们可以把点选式验证码的问题拆成两个小问题:

1、图片中的字都在哪儿?

即检测图片中所有的字的坐标。经过这一步,我们能把图片中的字都切割出来。

fd5383294ff8a6f35878456956c8bb1f.png

形象点说,就是找到上图中的所有框框的位置。进而,我们可以根据框框的坐标把字的图片切出来。

就像下图这样。

048e9b2bf73bd8cfd6f3f14b0b701362.png

2、切割出来的图片里面的字,是啥?

对于每一个切割出来的小图片,判断它是什么字,进而判断它是不是我们要点击的字。

2.2 一般流程

所以,解决这种问题,一般流程如下:

  • 1、使用爬虫抓取多张验证码图片

    • 图片越多,效果越好

  • 2、使用labelImg标注数据集

  • 3、使用标注好的数据集训练一个目标检测模型

    • 并不限制使用某种具体的模型或算法

    • 常见的诸如SSD、YOLO、R-CNN等都可以

  • 4、获取一个给定文字图片,输出文字的模型

    • 可以自己编写、标注并训练一个模型

    • 可以借助开源OCR工具,比如tesseract

    • 也可以借助第三方的OCR接口,比如百度的通用文字识别,每天五万次免费额度,非常良心

  • 5、获取标签部分要点击的文字

    • 如果html里面可以拿到,直接解析html就可以了

    • 如果标签部分给定的是图片,需要先借着4中的模型进行识别

  • 6、使用3中的目标检测模型对验证部分的图片进行检测,获取所有文字的坐标

  • 7、根据6中获取的坐标,切分文字图片,并逐一使用4中的模型识别出图片对应的汉字

  • 8、判断哪些坐标是需要点击的,按照正确的顺序点击它

上面这个是一般流程,是大家都喜欢使用的一种流程。那么问题来了——有没有不一般的流程?

有的!我要开始抖机灵了!

我们来仔细讨论一下上面流程的第4部分。这里需要获取一个图像转文字的模型,一般情况下,我们优先考虑现成的资源:

  • 开源OCR工具tesseract

  • 百度的通用文字识别接口

经测试,tesseract 对示例中给出的验证的识别效果很差(加载了中文tessdata也不行),基本上识别不出来。百度的接口对于标签部分的识别还不错,但对验证部分的识别效果也很差。

这也不能怪tesseract和百度OCR,毕竟这是为了反爬虫而刻意扭曲、加工的字体,他们的模型并没有在这种数据上进行训练,识别不出来也很正常。

那就只剩下一种选择了,自己实现模型完成图像转文字的任务。

怎么做?最简单、也最直接的想法就是:

  • 1、使用爬虫抓取验证码

  • 2、将验证码中的验证区域的字的图片都截取下来,标定它是什么字

  • 3、根据标定情况,构建词汇表和数据集

  • 4、使用卷积神经网络+softmax构建深度学习模型

  • 5、训练并调优

但这里存在一个问题,验证码图片中的文字并不是固定的几个字来回使用,而是随机的、很多字。

也就是说,词汇表的大小可能是10、100、1000甚至更大。

假设词汇表只是10,那么模型做的就是一个十分类问题,我们手工标定几百、多了的话上千张图片也够用了。

但如果词汇表是100、1000,我们面对的就是100、1000分类的问题。要想在这样的词汇大小下取得良好的识别效果的话,对数据规模的要求是很大的,标注上万张图片都不够。

标注这么多图片,只要想想都觉得好麻烦啊……

作为一条咸鱼的我并不想手工去标注那么多图片,一心想着偷懒的我,忽然灵机一动,我似乎,并不需要知道每个图片上的字是什么啊……

  • 标签区域的文字图片位置相对固定,可以直接截取下来

  • 验证区域的文字位置可以通过目标检测模型获得,进而截取出相应文字图片

两个图片我都有了,我管它图片上的文字是啥。对于标签区域的每一张文字图片,我只需要逐一判断验证区域的所有文字图片,和它是不是同一个字不就行了嘛。

也就是说,我不再需要一个100、1000分类的分类器了,只需要一个二分类器,把输入从一张图片改成两张图片,判断两张图片是否为同一个字就行了?!这样就把复杂问题变简单了,模型的复杂度能降下来,数据集的规模需求也能随之降下来,完美!

啧啧,怎么感觉这个想法这么眼熟呢?稍微思考一下,握草,这不就是NLP里面常用的负采样思想嘛???

后来去查了一下,发现类似的思路早有人提出来了,学名叫孪生神经网络……

可惜,错失发现新大陆的机会 [狗头] [狗头]

 97fcba361dcbca89cce29ae3720a0c4b.png

行吧,调整之后的流程大致如下:

  • 1、使用爬虫抓取多张验证码图片

    • 图片越多,效果越好

  • 2、使用labelImg标注数据集

  • 3、使用标注好的数据集训练一个目标检测模型

    • 并不限制使用某种具体的模型或算法

    • 常见的诸如SSD、YOLO、R-CNN等都可以

  • 4、使用孪生神经网络编写一个判别模型,输入两张图片,判断它们是不是同一个字

  • 5、截取标签区域的所有文字图片

  • 6、使用3中的目标检测模型对验证部分的图片进行检测,获取所有文字的坐标,进而切割出文字图片

  • 7、对于5中的每一个标签文字图片,使用4中的判别模型判断6中的哪一个生成文字图片,与它是同一个字

  • 8、判断哪些坐标是需要点击的,按照正确的顺序点击它

流程基本清楚了,那我们现在开始实战吧!

三、解决点选式验证码的实战示例

首先交代笔者使用的环境:

  • 操作系统:Mac OS X

  • Python发行版本:Anaconda

  • Python版本:3.7

  • TensorFlow版本:2.2

在Linux下的操作大部分是差不多的,在Win下的话我没有尝试,如果遇到问题的话可能要自行花点心力排查解决。

注意,我使用的Python是通过Anaconda安装的,所以我的python和pip指向的都是python3和pip3。请根据个人情况判断是否需要替换文章中的python和pip为python3和pip3。

正式开始了!

3.1 使用爬虫抓取多张验证码

# -*- coding: utf-8 -*-
import time
import requests
from tqdm import tqdm
for i in tqdm(range(300)):
    response = requests.get('http://xxxxxxxx/ValidateImage')
    with open('./images/{}.png'.format(i), 'wb') as f:
        f.write(response.content)
    time.sleep(2)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值