【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906

声明: 本文引用的网站仅用于演示,如侵删。

背景

这两天收到运营同事一个关于需要登录的网站的数据爬取需求,登录同时需要填入图片验证码。
经过多次尝试,结合百度OCR可以完成图片验证码的获取和识别,特此记录。
希望能帮助到需要的朋友们。

前期准备

  1. 部署好的可访问的可视化爬虫spiderflow,可参考笔者之前的文章。

    • 可视化爬虫框架spiderflow入门及实战
    • 基于docker-compose快速部署springboot应用的实践
  2. 百度云OCR申请,可自行注册。

    • 个人认证可申请每月1000次的免费额度,企业认证每月2000次免费额度,测试足够了。
    • 认证完成后注册应用,选择支持OCR图片识别。
      【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第1张图片
  3. 一个有图片验证码的目标网站

    说明:

    图片验证码的数据及展现形式有多种,如后端直接返回文件流,返回base64,前端自行渲染等,

    本文仅讨论后端返回文件流和base64的两种情况。

开始

1. spiderflow集成ocr

这一步有现成的插件可以用,在gitee 上搜索spider-flow-ocr即可。
附地址参考: spider-flow OCR插件

用法也比较简单,在spider-flow-web的pom文件中添加如下依赖即可

<dependency>
 	<groupId>org.spiderflowgroupId>
 	<artifactId>spider-flow-ocrartifactId>
 	<version>${spider-flow.version}version>
dependency>

添加完成后重新运行spiderflow项目,访问首页可看到如下页面:
【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第2张图片
点击添加OCR配置,进入配置页面,填入百度云创建的应用对应的参数。
【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第3张图片
【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第4张图片
同时在爬虫列表页面点击添加爬虫,看到如下图标及配置即表示OCR集成成功。
【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第5张图片

2. 获取验证码数据

首先找到获取验证码的链接,一般都可以在F12中找到对应请求,将请求记录下来,有的网站甚至需要添加指定的cookie或者请求头。

这里我使用的网站的验证码数据效果是这样的:
【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第6张图片
【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第7张图片
截图所示为关键请求头数据,除Cookie外其余属性需要添加到Header中。

PS: 如果上面的请求头不能正确返回数据,可尝试复制所有的请求头到spiderflow中。

3. 完成识别并查看结果

通过2的演示可以看到这里返回的直接就是一张图片,我们现在有两种思路:

  • 保存图片到临时目录,再上传图片到OCR
  • 直接提交byte到OCR

接下来就这两种思路分别做实现,同时也演示下spiderflow中文件和流的使用。

3.1 先保存到本地再上传

3.1.1 新建爬虫,并拖拽组件

如下图:

【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第8张图片
爬虫组件除配置URL外还需要加入对应的cookie和header,cookie和header均支持批量添加,还是挺方便的。

3.1.2 配置文件保存

【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第9张图片
用到了file.write方法,有三个参数,第一个是存储路径,第二个是个InputStream流,第三个是append参数,这里是false。

这样文件就存储到了/tmp/result.png中,后面运行后我们再验证。

3.1.3 配置OCR

【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第10张图片

3.1.4 输出结果

【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第11张图片

3.1.5 结果验证

保存并运行,查看/tmp/result.png文件是否存在,同时验证结果输出是否正确,效果如下:

【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第12张图片
【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第13张图片
可以看到文件存在且文件对应的验证码和输出的验证码一致,实验结束。

总的来说,整个流程还是非常简单的,借助于spiderflow非常优秀的插件机制,ocr插件的出现使得ocr的使用非常方便,给作者点个大大的赞。

当然这个ocr插件只实现了百度OCR的集成,如果需要别的平台可参考添加实现即可。

3.2 直接上传并识别

上面我们实现了文件保存到本地再上传到ocr的过程,可以说是为了验证。接下来我们直接上传http响应到ocr来实现。

3.2.1 新建爬虫,拖拽组件如下图

【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第14张图片
相比上个实现过程少了保存文件的过程,可想而知也就没有了读取文件的过程

3.2.2 爬虫配置

爬虫配置与3.1.1中配置一致,配置URL, header和cookie,不再赘述。

3.2.3 OCR配置

【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第15张图片

3.2.4 输出结果

配置同3.1.4,运行结果如下图:

【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第16张图片

4. 获取base64对应的验证码

思路一: 解析base64为本地图片,再上传

关于解析base64为本地图片,原代码是有点问题的,简单调整下即可,涉及文件FileFunctionExecutor.java

需要添加和修改的方法如下:

/**
 * 新添加的方法,兼容图片的base64编码
 */
private static byte[] toBytes(String content, String charset){
    if(content.startsWith("data:")){
        String data = content.substring(content.indexOf(",") + 1);
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            //Base64解码
            byte[] b = decoder.decodeBuffer(data);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    //调整异常数据
                    b[i] += 256;
                }
            }
            return b;
        }catch(Exception ex) {
            ex.printStackTrace();
        }
    }
    return StringFunctionExecutor.bytes(content, charset);
}

/**
 * toBytes方法使用
 * 修改原有方法
 */
@Comment("写出文件")
@Example("${file.write('e:/result.html',resp.html,'UTF-8',false)}")
public static void write(String path,String content,String charset,boolean append) throws IOException{
    write(path,toBytes(content, charset),append);
}

关于字符串转byte数组,原文件中是直接调用StringFunctionExecutor.bytes(content, charset)来完成的,这种并不能兼容图片的base64,所以做了个简单的调整。

对应爬虫的流程图配置如下:
【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第17张图片
查看本地图片,如下:
【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906_第18张图片
可以看到文件可以正常转换及存储, 接下来就可以上传这个文件到OCR实现识别了,步骤同3.1

这种方式不一定是最优解,确实能想到的最直接的办法(想到了另一种方式,暂且保留吧)

PS: 这里为了示例随便找了个图片通过在线转的base64,实际情况一般是通过接口获取。

思路二:获取到图片对应的base64字符串的byte数组

聪明的小伙伴一定都猜到了,这里要改写base64解码的相关代码了。

涉及到的类Base64FunctionExecutor.java, 具体实现留给各位小伙伴去探索吧。

思路三:各位小伙伴有更好的主意欢迎留言

到此本文要介绍的内容就结束了。

总结

本文介绍了基于spiderflow+ocr插件实现的图片验证码的获取与识别,整体过程相对来说比较简单,希望能对大家有所帮助吧。

spiderflow提供了非常优秀的插件机制,具备很高的扩展性,值得我们学习和研究,同时提供了很多很实用的方法。

实现了验证码的获取和识别,离实现登录又近了一步,为难的是网站提交的密码数据是加密后的,即使知道了用户名密码也要找到正确的加密算法才行,需要用到js逆向,还是得继续努力呀~~~~

如果本文对你有所帮助,欢迎一键三连~~~

针对以上内容或者spiderflow有任何疑问欢迎留言交流~~~~

你可能感兴趣的:(工作记录,爬虫,ocr,网络爬虫)