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

这几年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这个两个文件夹。

Java 爬虫之识别图片验证码后登录_第1张图片

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

     /**
     * 
     * @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爬虫要用在正途上,毕竟最近也听说了有爬虫工程师被抓判刑的消息,所谓细水长流,我们要走可持续发展的道路。

你可能感兴趣的:(Java)