liujijiang

基于crawler4j框架的java爬虫爬取图片

2020.02.06

简介

crawler4j是一个开源的Java抓取Web爬虫,它提供了一个简单的抓取Web的界面。 使用它,你可以在几分钟内设置一个多线程的网络爬虫。

maven添加依赖

在pom.xml中添加依赖

	<dependency>
            <groupId>edu.uci.ics</groupId>
            <artifactId>crawler4j</artifactId>
            <version>4.3</version>
        </dependency>

写一个爬虫扩展WebCrawler的类

package com.spider;

import java.io.File;
import java.io.IOException;
import java.util.UUID;
import java.util.regex.Pattern;

import com.google.common.io.Files;

import edu.uci.ics.crawler4j.crawler.Page;
import edu.uci.ics.crawler4j.crawler.WebCrawler;
import edu.uci.ics.crawler4j.parser.BinaryParseData;
import edu.uci.ics.crawler4j.url.WebURL;

/*
 * 这个类主要是爬取图片,并且存储到指定文件夹
 */

public class MyCrawler extends WebCrawler {

    /*
     * 指定文件后缀过滤
     */
    private static final Pattern filters = Pattern
            .compile(".*(\\.(css|js|mid|mp2|mp3|mp4|wav|avi|mov|mpeg|ram|m4v|pdf" + "|rm|smil|wmv|swf|wma|zip|rar|gz))$");

    /*
     * 正则匹配图片文件
     */
    private static final Pattern imgPatterns = Pattern.compile(".*(\\.(bmp|gif|jpe?g|png|tiff?))$");

    private static File storageFolder; // 爬取的图片本地存储地址
    private static String[] crawlDomains; // 指定要爬取的域名

    /**
     * 配置方法 指定域名和本地存储文件
     * @param domain
     * @param storageFolderName
     */
    public static void configure(String[] domain, String storageFolderName) {
        crawlDomains = domain;

        storageFolder = new File(storageFolderName); // 实例化
        if (!storageFolder.exists()) { // 假如文件不存在
            storageFolder.mkdirs(); // 我们创建一个
        }
    }

    /**
     * 这个方法主要是决定哪些url我们需要抓取,返回true表示是我们需要的,返回false表示不是我们需要的Url
     * 第一个参数referringPage封装了当前爬取的页面信息
     * 第二个参数url封装了当前爬取的页面url信息
     */
    @Override
    public boolean shouldVisit(Page referringPage, WebURL url) {
        String href = url.getURL().toLowerCase(); // 得到小写的url
        if (filters.matcher(href).matches()) { // 过滤指定后缀url
            return false;
        }

        if (imgPatterns.matcher(href).matches()) { // 匹配指定图片后缀文件
            return true;
        }

        for (String domain : crawlDomains) { // 匹配指定域名
            if (href.startsWith(domain)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 当我们爬到我们需要的页面,这个方法会被调用,我们可以尽情的处理这个页面
     * page参数封装了所有页面信息
     */
    @Override
    public void visit(Page page) {
        String url = page.getWebURL().getURL(); // 获取url

        // 只爬取大于等于10kB的图片文件
        if (!imgPatterns.matcher(url).matches() ||
                !((page.getParseData() instanceof BinaryParseData) || (page.getContentData().length < (10 * 1024)))) {
            return;
        }

        // 获取图片后缀
        String extension = url.substring(url.lastIndexOf('.'));
        String hashedName = UUID.randomUUID() + extension; // 通过uuid 拼接成唯一图片名称

        // 定义存储文件
        String filename = storageFolder.getAbsolutePath() + "/" + hashedName;
        try {
            Files.write(page.getContentData(), new File(filename)); // 把爬取到的文件存储到指定文件
            System.out.println("爬取图片的url:"+url);
        } catch (IOException iox) {
            iox.printStackTrace();
        }
    }
}

这个类的中主要有两个需要继承WebCrawler的方法
ShouldVisit和Visit方法

  • shouldvisit方法:这个方法是决定哪个url是我们想要访问的,返回true表示需要访问,false表示不访问。
  • visit方法:这个方法是当我们访问一个我们想访问的URL时,我们想怎么操作,想提取什么信息。

写一个爬虫控制类

package com.spider;


import edu.uci.ics.crawler4j.crawler.CrawlConfig;
import edu.uci.ics.crawler4j.crawler.CrawlController;
import edu.uci.ics.crawler4j.fetcher.PageFetcher;
import edu.uci.ics.crawler4j.robotstxt.RobotstxtConfig;
import edu.uci.ics.crawler4j.robotstxt.RobotstxtServer;

/**
 * 图片爬虫控制器
 * @author user
 *
 */
public class Controller {

    public static void main(String[] args) throws Exception {


        String rootFolder =  "/Users/joker/Documents/ideaProjects/spider/news"; // 定义爬虫数据存储位置
        int numberOfCrawlers = 7; // 定义7个爬虫,也就是7个线程
        String storageFolder = "/Users/joker/Documents/ideaProjects/spider/news/photos"; // 定义爬取的图片本地存储位置

        CrawlConfig config = new CrawlConfig(); // 实例化爬虫配置

        config.setCrawlStorageFolder(rootFolder); // 设置爬虫文件存储位置

        /*
         * 设置允许爬取二进制文件
         * 因为图片属于二进制文件
         */
        config.setIncludeBinaryContentInCrawling(true);

        String[] crawlDomains = {"http://www.netbian.com"};

        /*
         * 实例化爬虫控制器
         */
        PageFetcher pageFetcher = new PageFetcher(config); // 实例化页面获取器
        RobotstxtConfig robotstxtConfig = new RobotstxtConfig(); // 实例化爬虫机器人配置 比如可以设置 user-agent

        // 实例化爬虫机器人对目标服务器的配置,每个网站都有一个robots.txt文件 规定了该网站哪些页面可以爬,哪些页面禁止爬,该类是对robots.txt规范的实现
        RobotstxtServer robotstxtServer = new RobotstxtServer(robotstxtConfig, pageFetcher);
        // 实例化爬虫控制器
        CrawlController controller = new CrawlController(config, pageFetcher, robotstxtServer);

        /*
         * 配置爬虫种子页面,就是规定的从哪里开始爬,可以配置多个种子页面
         */
        for (String domain : crawlDomains) {
            controller.addSeed(domain);
        }

        MyCrawler.configure(crawlDomains, storageFolder); // 配置爬虫域名,以及本地存储位置

        /*
         * 启动爬虫,爬虫从此刻开始执行爬虫任务,根据以上配置
         */
        controller.start(MyCrawler.class, numberOfCrawlers);
    }
}

这个这种定义了爬虫文件和我们想要的资源的保存位置,还有爬取的种子网站,爬虫个数(进程个数)。