美文网首页
Java中while循环的使用(二):反复识别验证码图片,直到正

Java中while循环的使用(二):反复识别验证码图片,直到正

作者: 墨色尘埃 | 来源:发表于2020-05-20 17:48 被阅读0次

    批量发送邮件

    上文中技术点二,用到了百度文字识别api,以及多次识别验证码,直到正确为止,用到了while循环

    pom中引入百度api依赖

            <dependency>
                <groupId>com.baidu.aip</groupId>
                <artifactId>java-sdk</artifactId>
                <version>4.8.0</version>
            </dependency>
    

    如果这种方式引入不进来,可以使用lib包下放入jar包的方式引入

    image.png

    然后pom.xml中引入

            <!--百度文字识别-->
            <dependency>
                <groupId>com.baidu.aip</groupId>
                <artifactId>java-sdk</artifactId>
                <version>4.11.0</version>
                <scope>system</scope>
                <systemPath>${project.basedir}/lib/aip-java-sdk-4.11.1.jar</systemPath>
            </dependency>
    

    利用百度文字识别API识别图像中的文字
    https://cloud.baidu.com/doc/OCR/index.html

    验证码识别的代码如下

        /**
         * 验证码,经过百度文字识别api之后,识别出图片中的文字
         * 递归调用,貌似有问题,返回多次数据
         *
         * @param userId
         * @return
         * @throws IOException
         */
        public String checkHandleCode(String userId) throws Exception {
    
            JSONArray wordsResult = checkWordsResult(userId);
            boolean jsonArrayEmptyFlag = true;
            while (jsonArrayEmptyFlag) {
                if (wordsResult.size() == 0 || org.springframework.util.StringUtils.isEmpty(wordsResult)) {
                    wordsResult = null;
                    jsonArrayEmptyFlag = false;
                    wordsResult = checkWordsResult(userId);
                } else {
                    jsonArrayEmptyFlag = false;
                }
            }
    
            com.alibaba.fastjson.JSONObject o = (com.alibaba.fastjson.JSONObject) wordsResult.get(0);
            String words = (String) o.get("words");
    
            //取出百度文字识别,未经处理的文字,判断是否为空
            //为空,获取下一张验证码继续识别
            //不为空,跳出循环,执行下一步
    
    //        // 模拟出错状态
    //        String[] randomArray = {words, null, ""};
    //        int i = (int) (Math.random() * randomArray.length);
    //        words = randomArray[i];
    
            boolean emptyFlag = true;
            while (emptyFlag) {
                if (org.springframework.util.StringUtils.isEmpty(words)) {
                    words = null;
                    emptyFlag = false;
                    words = checkHandleCode(userId);
                } else {
                    emptyFlag = false;
                    break;
                }
            }
    
            //最原始的未经处理的文字,不为空之后,去除空格后的新String判断是否为空
            //为空,获取下一张验证码继续识别
            //不为空,跳出循环,执行下一步
            words = words.replace(" ", "");
            boolean replaceFlag = true;
            while (replaceFlag) {
                if (org.springframework.util.StringUtils.isEmpty(words)) {
                    words = null;
                    replaceFlag = false;
                    words = checkHandleCode(userId);
                } else {
                    replaceFlag = false;
                    break;
                }
            }
    
            //判断新String是否是4位
            //不等于4,获取下一张验证码继续识别
            //等于4,跳出循环,执行下一步
            boolean fourCharFlag = true;
            while (fourCharFlag) {
                if (words.length() != 4) {
                    //递归调用中,如果当前验证码不符合四位,又会调用自己的方法
                    //但是上一个自己的方法还没有结束,变量生命周期没有结束(见引申),所以必须对该变量修改,恢复原值
                    //引申:虚拟机栈描述的是JAVA方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(STACKFRAME
                    // )用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈和出栈的过程。
                    words = null;
                    fourCharFlag = false;
                    words = checkHandleCode(userId);
                } else {
                    fourCharFlag = false;
                    break;
                }
            }
            return words;
        }
    

    重点看这几段代码

            boolean emptyFlag = true;
            while (emptyFlag) {
                if (org.springframework.util.StringUtils.isEmpty(words)) {
                    words = null;
                    emptyFlag = false;
                    words = checkHandleCode(userId);
                } else {
                    emptyFlag = false;
                    break;
                }
            }
    

    第一次进入这里
    先定义了一个局部变量boolean emptyFlag = true,进入while循环,如果上一步识别到的验证码图片上的words是空的话,则再次进行识别(即再次调用该方法,递归)

    再次调用该方法,如果一切顺利,第二次进入到这里
    然后会再次定义一个局部变量boolean emptyFlag = true,进入while循环,第二次判断识别到的验证码图片上的words
    如果为空,则再次递归
    如果不为空,则结束第二次的方法,返回第一次调用的方法中(返回第一次调用方法的while处)
    这里一定要设置emptyFlag为false,因为是局部变量,如果第一次进到到if条件里没有设置的话,当第二次方法调用结束回到第一次方法的while处时,此处的emptyFlag还是true,就会进入死循环

    image.png

    递归的过程大概如下

    image.png

    相关文章

      网友评论

          本文标题:Java中while循环的使用(二):反复识别验证码图片,直到正

          本文链接:https://www.haomeiwen.com/subject/ymygohtx.html