java使用Crawler4j开发爬虫

原创
2016/12/01 22:11
阅读数 933

在爬虫开发中,常用的语言是python,但是也可以使用java来进行 开发,这样就可以利用java强大的库,下面就来介绍一下常用的java爬虫框架。

Crawler4j

官网:https://github.com/yasserg/crawler4j
开发顺序:

  1. 定制Controller层,用于控制爬虫的行为
  2. 使用main()直接开始程序即可

下面上代码:

// 此类用于控制爬虫爬取网页的图片,并且将图片存储在本地
public class ImageCrawler 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;
    // 爬虫会爬取的域,可以是一个普通的URL
    private static String[] crawlDomains;

    // 初始化Controller
    public static void configure(String[] domain, String storageFolderName) {
        crawlDomains = domain;

        storageFolder = new File(storageFolderName);
        if (!storageFolder.exists()) {
            storageFolder.mkdirs();
        }
    }

    @Override
    // 确定需不需要下载url所指定的资源
    public boolean shouldVisit(Page referringPage, WebURL url) {
        String href = url.getURL().toLowerCase();
        // 和过滤器相匹配,不下载 
        if (filters.matcher(href).matches()) {
            return false;
        }

        // 是图片,下载
        if (imgPatterns.matcher(href).matches()) {
            return true;
        }

        // 如果是网页,进行url匹配,看是不是在需要下载的域内部
        for (String domain : crawlDomains) {
            // 在需要下载的域内
            if (href.startsWith(domain)) {
                return true;
            }
        }
        return false;
    }

    // shouldVisit为true,则会调用此函数
    @Override
    public void visit(Page page) {
        String url = page.getWebURL().getURL();

        // 如果是图片,并且图片大小在10kb以内,就不访问
        if (!imgPatterns.matcher(url).matches() ||
            !((page.getParseData() instanceof BinaryParseData) ||
              (page.getContentData().length < (10 * 1024)))) {
            return;
        }

        // get a unique name for storing this image
        // 获取图片的格式
        String extension = url.substring(url.lastIndexOf('.'));
        // 获取图片的名称,此处是随机值
        String hashedName = UUID.randomUUID() + extension;

        // 存储图片
        String filename = storageFolder.getAbsolutePath() + "/" + hashedName;
        try {
            // 写入文件系统,并且输出到磁盘
            Files.write(page.getContentData(), new File(filename));
            logger.info("Stored: {}", url);
        } catch (IOException iox) {
            logger.error("Failed to write file: " + filename, iox);
        }
    }
}

下面是启动爬虫所用:

public class ImageCrawlController {
    private static final Logger logger = LoggerFactory.getLogger(ImageCrawlController.class);

    public static void main(String[] args) throws Exception {
        // 爬虫参数控制,需要传入3个参数
        // 存储路径,这个是存储爬虫的运行时数据的
        // 并行线程数量
        // 图片存储路径
        if (args.length < 3) {
            logger.info("Needed parameters: ");
            logger.info("\t rootFolder (it will contain intermediate crawl data)");
            logger.info("\t numberOfCralwers (number of concurrent threads)");
            logger.info("\t storageFolder (a folder for storing downloaded images)");
            return;
        }

        String rootFolder = args[0];
        int numberOfCrawlers = Integer.parseInt(args[1]);
        String storageFolder = args[2];

        CrawlConfig config = new CrawlConfig();
        // 设置运行数据存储路径
        config.setCrawlStorageFolder(rootFolder);
        // 下载二进制数据(图片是二进制的数据)
        config.setIncludeBinaryContentInCrawling(true);
        // 需要爬的网站
        String[] crawlDomains = {"http://uci.edu/"};
        // PageFetcher是用于下载数据的 
        PageFetcher pageFetcher = new PageFetcher(config);
        // 用于控制是否遵守robots协议
        RobotstxtConfig robotstxtConfig = new RobotstxtConfig();
        RobotstxtServer robotstxtServer = new RobotstxtServer(robotstxtConfig, pageFetcher);
        CrawlController controller = new CrawlController(config, pageFetcher, robotstxtServer);
        // 添加爬虫最初爬取的网页
        for (String domain : crawlDomains) {
            controller.addSeed(domain);
        }

        ImageCrawler.configure(crawlDomains, storageFolder);
        // 启动爬虫,使用并行
        controller.start(ImageCrawler.class, numberOfCrawlers);
    }
}

#Tip:本文所用代码是Crawler4j官方代码,只是稍作注解而已

展开阅读全文
打赏
0
3 收藏
分享
加载中
更多评论
打赏
0 评论
3 收藏
0
分享
返回顶部
顶部