0

    Java 爬虫之识别图片验证码后登录

    2023.07.31 | admin | 147次围观

    这几年Python爬虫特别的火,我有个朋友是一个Python爬虫工程师,本人菜鸡Java开发工程师一名,最近所做的一个项目是需要去爬一个网页的数据,但是进入网页需要登录,登录需要输入图片验证码。爬虫的第三方jar包用的是jsoup,图片识别用的是tesj4j。话不多硕,上demo,奥利给!

    一、下载jsoup.jar、tess4j的jar包,或者maven引入jsoup和tess4j的jar包。在windows环境下,但是tess4j本地开发需要调用dll文件还是需要的的,下载地址:点我。如下图一,是tess4j下载解压的完整目录,dist放的是tess4j的jar包,如果你用的是maven,就直接导入这个tess4j版本的jar,lib放的是windows执行的dll文件和开发中需要用的、依赖的jar包验证码背景图片下载验证码背景图片下载,tessdata是字库,我这里是纯识别数字,所以没有引入中文字库。我用的是maven,所以就只需要lib和tessdata这个两个文件夹。

    二、获取验证码图片,识别图片中的验证码,设置用户名、密码,保持会话进行登录。

         /**
         * 
         * @param url 系统地址
         * @param user 用户名
         * @param pwd 密码
         * @param tess4jpath tess4j的地址 如G:\test\Tess4J-3.4.8-src\Tess4J
         * @return
         */
        public Map login(String url, String user, String pwd,String tess4jpath) {
            Map map = null;
            Connection.Response LoginResponse = null;
            try {
                LoginResponse = Jsoup.connect(url).method(Connection.Method.GET).execute();
                map = LoginResponse.cookies();//获取会话,登录后需要保持会话
                Document document = LoginResponse.parse();
                Element element = document.getElementById("验证码图片标签");
                String codeimgurl = url+element.attr("src");
                String codeimgpath = tess4jpath+"\\codeimg";
                //下载验证码图片
                byte[] codeimgdata = Jsoup.connect(codeimgurl).ignoreContentType(true).execute().bodyAsBytes();
                FileUtils.saveImg(codeimgdata, codeimgpath, "codeimg.jpg");
                //识别样本输出地址
                String ocrResult = codeimgpath+"\\codetmpimgtmp.jpg";
                String OriginalImg = codeimgpath+"\\codeimg.jpg";
                //去噪点
                FileUtils.removeBackground(OriginalImg, ocrResult);
                ITesseract instance =new Tesseract();
                instance.setDatapath(tess4jpath);
                File imgDir =new File(ocrResult);
                String code = instance.doOCR(imgDir);//识别验证码
                System.out.println("code:"+code); 
                Map datas = new HashMap();
                datas.put("user", user);
                datas.put("pwd", pwd);
                datas.put("ident",code);
                Connection connection = Jsoup.connect(url+"/login?op=userLogin");
                //输入用户名和密码保持会话登录
                Connection.Response response1 = connection.data(datas).cookies(map).method(Connection.Method.POST).execute();
            } catch (IOException e) {
                map = null;
                e.printStackTrace();
            } catch (TesseractException e) {
                map = null;
                e.printStackTrace();
            }finally {
                return map;
            }
        }

    上述代码中使用的工具类

    public class FileUtils {
        /**
         * 级联创建目录
         * @param path
         */
        public static void creatDir(String path) {
            File file = new File(path);
            if(!file.exists()) {
                file.mkdirs();
            }
        }
        /**
         * 验证码图片处理
         * @param imgUrl
         * @param resUrl
         */
        public static void removeBackground(String imgUrl, String resUrl){
            //定义一个临界阈值
            int threshold = 300;
            try{
                BufferedImage img = ImageIO.read(new File(imgUrl));
                int width = img.getWidth();
                int height = img.getHeight();
                for(int i = 1;i < width;i++){
                    for (int x = 0; x < width; x++){
                        for (int y = 0; y < height; y++){
                            Color color = new Color(img.getRGB(x, y));
                            //System.out.println("red:"+color.getRed()+" | green:"+color.getGreen()+" | blue:"+color.getBlue());
                            int num = color.getRed()+color.getGreen()+color.getBlue();
                            if(num >= threshold){
                                img.setRGB(x, y, Color.WHITE.getRGB());
                            }
                        }
                    }
                }
                for(int i = 1;i

    注意:并不是所有的系统的验证码都能识别,就拿这个12306来说,我也不知道怎么识别,关键是我也不敢问啊!我识别的验证码是简单的数字验证码,原始验证码

    ,去噪的验证码

    ,去噪后的验证码便于识别数字。

    不管怎么样,希望你使用的Java爬虫要用在正途上,毕竟最近也听说了有爬虫工程师被抓判刑的消息,所谓细水长流,我们要走可持续发展的道路。

    版权声明

    本文仅代表作者观点。
    本文系作者授权发表,未经许可,不得转载。

    发表评论