简单爬虫设计(二)——如何建模爬虫的爬取范围

前言

如果还没有阅读前序文章,可以移步到:简单爬虫设计(一)——基本模型

基本概念

爬取范围(Crawling Scope)是爬虫的输入,是爬取任务(Crawling Task)的一部分。爬取范围作为统一语言的一部分,可以让模型更易读。

统一语言,是领域驱动设计引入的一个重要概念,统一语言让业务方和开发方能够使用一套词汇进行沟通,好的领域模型也可以充当统一语言。

在该系列的第一篇文章简单爬虫设计(一)——基本模型 中,对爬取范围进行了显式建模,并讨论了爬取范围需要包含的数据项,这里再简单回顾一下每个数据项的含义。

  • 起始网址(爬取深度为0)
  • 从起始网址开始要遍历的链接最大深度,也称为采集深度或最大跳数
  • 要遍历的链接特征
  • 遍历链接数量最大值
  • 是否只采集域名内链接等

在具体实现的时候,链接特征需要考虑到各种复杂情况,这里先只考虑字符串特征和正则表达式特征。

举个例子

下面用一个具体例子来说明这些数据项的用法。

  1. 我们假设要爬取一个博客网站,比如酷壳网。
  2. 起始网址可以设置为网站首页地址https://coolshell.cn。
  3. 根据这个网站的特点,采集深度可以设置为3,基本可以遍历到所有历史文章。
  4. 要遍历的链接可以是站内所有链接,如果用正则表达式表示的话,可以是https://coolshell\.cn/.+,其中的“.+”表示匹配任意字符。需要说明,遍历的链接并不是最终要保存或者继续处理的链接。
  5. 遍历的链接数量最大值可以不设置,意味着不限制数量。
  6. 设置只采集域名内的链接。如果设置了需要遍历的链接特征,这个设置就没有用了,可以忽略。

通过这个例子,基本可以了解爬取范围的设置了。下面来看具体的实现代码。

代码示例

interface CrawlingScope {  //接口定义
    List<String> startUrls();

    boolean contains(Link link);

    long maxToCrawl();

    int maxHops();
}

class CrawlingScopeImpl {  //实现类
    //起始URL,第0跳
    private List<String> startUrls;

    //从起始URL开始计算跳数
    private int maxHops;

    //指定正则表达式规则的URL会继续爬取
    private String urlCrawlRegex;

    //包含特定字符串特征的URL会继续爬取
    private String urlCrawlStrPattern;

    //最多爬取多少页面
    private long maxToCrawl = Long.MAX_VALUE;
    
    //限制到起始URL的域名
    private boolean restrictDomain;

    public boolean contains(Link link) {
        String url = link.getUrl();

        for (String startUrl : this.startUrls) {
            if (link.getUrl().equalsIgnoreCase(startUrl)) {
                return true;
            }
        }

        if (link.getDepth() > this.maxHops) {
            return false;
        }

        if (this.restrictDomain && !isUnderDomain(url)) {
            return false;
        }

        UrlFilter urlFilter = new UrlFilter(
                this.urlCrawlStrPattern, this.urlCrawlRegex);
        return urlFilter.isMatch(url);
    }
    
    
}

使用CrawlingScope的代码示例。

public void crawl(){

    fetchAndProcess(target);  //爬取并处理

    //如果爬取链接总数大于最大限制
    if (this.fetchedLinks.total() >= crawlingScope.maxToCrawl()) {
        return;
    }

    //省略部分代码
    if (this.crawlingScope.contains(link) &&   //链接在爬取范围内  
        !this.fetchedLinks.contains(link)) {   //如果链接还没被爬取过
            targetLinks.add(link);         //加入待爬取集合
    }
}

小结

以上就是爬取范围的设计和实现。通过对爬取范围进行显式建模,能够让相关概念聚集在一起,爬虫的设计和实现也更加清晰。下一篇文章将实现ProcessingScope,也就是需要处理的网页范围。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值