该事例演示了如何在多线程中统计和分析数据;

首先建一个状态实体类CrawlStat:

package com.demo.collectingData;

/**
* 爬虫状态实体类 统计爬虫信息
* @author
*
*/
public class CrawlStat {
private int totalProcessedPages; //处理的页面总数
private long totalLinks; // 总链接数
private long totalTextSize; // 总文本长度 public int getTotalProcessedPages() {
return totalProcessedPages;
} public void setTotalProcessedPages(int totalProcessedPages) {
this.totalProcessedPages = totalProcessedPages;
} /**
* 总处理页面数加1
*/
public void incProcessedPages() {
this.totalProcessedPages++;
} public long getTotalLinks() {
return totalLinks;
} public void setTotalLinks(long totalLinks) {
this.totalLinks = totalLinks;
} public long getTotalTextSize() {
return totalTextSize;
} public void setTotalTextSize(long totalTextSize) {
this.totalTextSize = totalTextSize;
} /**
* 总链接数加count个
* @param count
*/
public void incTotalLinks(int count) {
this.totalLinks += count;
} /**
* 总文本长度加total个
* @param count
*/
public void incTotalTextSize(int count) {
this.totalTextSize += count;
}
}

再建一个LocalDataCollectorCrawler类:

package com.demo.collectingData;

import java.io.UnsupportedEncodingException;
import java.util.Set;
import java.util.regex.Pattern; import edu.uci.ics.crawler4j.crawler.Page;
import edu.uci.ics.crawler4j.crawler.WebCrawler;
import edu.uci.ics.crawler4j.parser.HtmlParseData;
import edu.uci.ics.crawler4j.url.WebURL; /**
* 该类演示了如何在多线程中统计和分析数据
* @author user
*
*/
public class LocalDataCollectorCrawler extends WebCrawler { // 正则匹配后缀
private static final Pattern FILTERS = Pattern.compile(
".*(\\.(css|js|bmp|gif|jpe?g|png|tiff?|mid|mp2|mp3|mp4|wav|avi|mov|mpeg|ram|m4v|pdf" +
"|rm|smil|wmv|swf|wma|zip|rar|gz))$"); CrawlStat myCrawlStat; // 定义爬虫状态对象,用户统计和分析 /**
* 构造方法
*/
public LocalDataCollectorCrawler() {
myCrawlStat = new CrawlStat(); // 实例化爬虫状态对象
} /**
* 这个方法主要是决定哪些url我们需要抓取,返回true表示是我们需要的,返回false表示不是我们需要的Url
* 第一个参数referringPage封装了当前爬取的页面信息
* 第二个参数url封装了当前爬取的页面url信息
*/
@Override
public boolean shouldVisit(Page referringPage, WebURL url) {
String href = url.getURL().toLowerCase(); // 获取url小写
return !FILTERS.matcher(href).matches() && href.startsWith("http://www.xxx.com"); // 必须是www.xxx.com域名
} /**
* 当我们爬到我们需要的页面,这个方法会被调用,我们可以尽情的处理这个页面
* page参数封装了所有页面信息
*/
@Override
public void visit(Page page) {
System.out.println("正在爬取页面:"+page.getWebURL().getURL());
myCrawlStat.incProcessedPages(); // 处理页面加1 if (page.getParseData() instanceof HtmlParseData) { // 假如是html数据
HtmlParseData parseData = (HtmlParseData) page.getParseData(); // 获取Html数据
Set<WebURL> links = parseData.getOutgoingUrls(); // 获取输出链接
myCrawlStat.incTotalLinks(links.size()); // 总链接加link.size个
try {
myCrawlStat.incTotalTextSize(parseData.getText().getBytes("UTF-8").length); // 文本长度增加
} catch (UnsupportedEncodingException ignored) {
// Do nothing
}
}
// 每获取3个页面数据 我们处理下数据
if ((myCrawlStat.getTotalProcessedPages() % 3) == 0) {
dumpMyData();
}
} /**
* 获取下爬虫状态
*/
@Override
public Object getMyLocalData() {
return myCrawlStat;
} /**
* 当任务完成时调用
*/
@Override
public void onBeforeExit() {
dumpMyData(); // 处理处理
} /**
* 处理数据
*/
public void dumpMyData() {
int id = getMyId();
System.out.println("当前爬虫实例id:"+id);
System.out.println("总处理页面:"+myCrawlStat.getTotalProcessedPages());
System.out.println("总链接长度:"+myCrawlStat.getTotalLinks());
System.out.println("总文本长度:"+myCrawlStat.getTotalTextSize());
}
}

最后建一个控制器LocalDataCollectorController:

package com.demo.collectingData;

import java.util.List;

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 LocalDataCollectorController { public static void main(String[] args) throws Exception { String rootFolder = "c:/crawl"; // 定义爬虫数据存储位置
int numberOfCrawlers = 2; // 定义7个爬虫,也就是7个线程 CrawlConfig config = new CrawlConfig(); // 定义爬虫配置
config.setCrawlStorageFolder(rootFolder); // 设置爬虫文件存储位置
config.setMaxPagesToFetch(10); // 设置最大页面获取数
config.setPolitenessDelay(1000); // 设置爬取策略 1秒爬一次 // 实例化爬虫控制器
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); controller.addSeed("http://www.xxx.com"); // 添加爬虫种子 // 启动爬虫,爬虫从此刻开始执行爬虫任务,根据以上配置
controller.start(LocalDataCollectorCrawler.class, numberOfCrawlers); List<Object> crawlersLocalData = controller.getCrawlersLocalData(); // 当多个线程爬虫完成任务时,获取爬虫本地数据
long totalLinks = 0;
long totalTextSize = 0;
int totalProcessedPages = 0;
for (Object localData : crawlersLocalData) {
CrawlStat stat = (CrawlStat) localData;
totalLinks += stat.getTotalLinks();
totalTextSize += stat.getTotalTextSize();
totalProcessedPages += stat.getTotalProcessedPages();
} // 打印数据
System.out.println("统计数据:");
System.out.println("总处理页面:"+totalProcessedPages);
System.out.println("总链接长度:"+totalLinks);
System.out.println("总文本长度:"+totalTextSize);
}
}

打印结果:

正在爬取页面:http://www.xxx.com/
正在爬取页面:http://www.xxx.com/share/2814499085634560.htm
正在爬取页面:http://www.xxx.com/share/2519215530527744.htm
正在爬取页面:http://www.xxx.com/share/2783070349888512.htm
当前爬虫实例id:2
总处理页面:3
总链接长度:672
总文本长度:22295
正在爬取页面:http://www.xxx.com/share/2769260213275648.htm
正在爬取页面:http://www.xxx.com/share/kredis-p1-s1.htm
正在爬取页面:http://www.xxx.com/share/kswing-p1-s1.htm
当前爬虫实例id:2
总处理页面:6
总链接长度:1299
总文本长度:46674
正在爬取页面:http://www.xxx.com/share/kcodehaus-p1-s1.htm
正在爬取页面:http://www.xxx.com/user/2176279510861824.htm
正在爬取页面:http://www.xxx.com/blog/2881413902666752.htm
当前爬虫实例id:2
总处理页面:9
总链接长度:1617
总文本长度:90618
当前爬虫实例id:1
总处理页面:1
总链接长度:326
总文本长度:10321
当前爬虫实例id:2
总处理页面:9
总链接长度:1617
总文本长度:90618
统计数据:
总处理页面:10
总链接长度:1943
总文本长度:100939

  

crawler4j多线程爬虫统计分析数据的更多相关文章

  1. Python多线程爬虫与多种数据存储方式实现(Python爬虫实战2)

    1. 多进程爬虫 对于数据量较大的爬虫,对数据的处理要求较高时,可以采用python多进程或多线程的机制完成,多进程是指分配多个CPU处理程序,同一时刻只有一个CPU在工作,多线程是指进程内部有多个类 ...

  2. etlpy: 并行爬虫和数据清洗工具(开源)

    etlpy是python编写的网页数据抓取和清洗工具,核心文件etl.py不超过500行,具备如下特点 爬虫和清洗逻辑基于xml定义,不需手工编写 基于python生成器,流式处理,对内存无要求 内置 ...

  3. python多线程爬虫设计及实现示例

    爬虫的基本步骤分为:获取,解析,存储.假设这里获取和存储为io密集型(访问网络和数据存储),解析为cpu密集型.那么在设计多线程爬虫时主要有两种方案:第一种方案是一个线程完成三个步骤,然后运行多个线程 ...

  4. python爬虫入门(四)利用多线程爬虫

    多线程爬虫 先回顾前面学过的一些知识 1.一个cpu一次只能执行一个任务,多个cpu同时可以执行多个任务2.一个cpu一次只能执行一个进程,其它进程处于非运行状态3.进程里包含的执行单元叫线程,一个进 ...

  5. [原创]一款小巧、灵活的Java多线程爬虫框架(AiPa)

    1.简介 AiPa 是一款小巧,灵活,扩展性高的多线程爬虫框架. AiPa 依赖当下最简单的HTML解析器Jsoup. AiPa 只需要使用者提供网址集合,即可在多线程下自动爬取,并对一些异常进行处理 ...

  6. python多线程爬虫+批量下载斗图啦图片项目(关注、持续更新)

    python多线程爬虫项目() 爬取目标:斗图啦(起始url:http://www.doutula.com/photo/list/?page=1) 爬取内容:斗图啦全网图片 使用工具:requests ...

  7. 洗礼灵魂,修炼python(88)-- 知识拾遗篇 —— 线程(2)/多线程爬虫

    线程(下) 7.同步锁 这个例子很经典,实话说,这个例子我是直接照搬前辈的,并不是原创,不过真的也很有意思,请看: #!usr/bin/env python #-*- coding:utf-8 -*- ...

  8. Python爬虫开发【第1篇】【多线程爬虫及案例】

    糗事百科爬虫实例: 地址:http://www.qiushibaike.com/8hr/page/1 需求: 使用requests获取页面信息,用XPath / re 做数据提取 获取每个帖子里的用户 ...

  9. 【python3两小时快速入门】入门笔记03:简单爬虫+多线程爬虫

    作用,之间将目标网页保存金本地 1.爬虫代码修改自网络,目前运行平稳,博主需要的是精准爬取,数据量并不大,暂未加多线程. 2.分割策略是通过查询条件进行分类,循环启动多条线程. 1.单线程简单爬虫(第 ...

随机推荐

  1. Vue的前端路由

    vue-router-- 根据不同的地址找到不同的页面                                       (单页面应用:无需频繁的从后台刷新页面) 1,安装路由-->导 ...

  2. [原创]Eclipse 安卓开发几个异常的处理办法

    一.代码没有问题,就是报错,重启一下就会好.可以先clean再build; 二.R.Java丢失 网上讲了若干方法,有用android toos的,有clean再build的,我的解决办法是勾选bui ...

  3. Python 之 面向对象(一)

    一.dir内置函数 在标识符/数据后输入一个.,然后按下TAB键,ipython会 提示该对象能够调用的方法列表 使用内置函数dir传入标识符/数据后,可以查看对象内所有的属性及方法 #查看注释 de ...

  4. 当接口上配了 FeignClient 和 RequestMapping 两个注解,结果错误提示 重复mapping处理方法

    再接手老文档的时候,发现有这么一个问题 错误显示为: 原文档写法: 解决方法: 这是一个编译时写法的问题,将上方的RequestMapping去掉,然后把路径放在下面的PostMapping 便可以正 ...

  5. java中参数传递实例

    //在函数中传递基本数据类型,            2. public class Test {         4.     public static void change(int i, in ...

  6. 数据仓库模型建设基础及kimball建模方法总结

    观察数据的角度称之为维.决策数据市多为数据,多维数据分析是决策分析的组要内容. OLAP是在OLTP的基础上发展起来的,OLTP是以数据库为基础的,面对的是操作人员和底层管理人员,对基本数据进行查询和 ...

  7. EF Code First连接现有数据库

    作为一个初入学习.net MVC4 的新手,想写一写今天碰到的问题,做一个总结. 首先我想利用EF Code First来连接我现有数据库,而不是通过EF Code First来自动生成数据库和表. ...

  8. nginx (待更新)

    install apt install nginx 默认在 /etc/nginx 目录下 一个 master 以及多个 worker 3504 root 20 0 141M 7196 5552 S 0 ...

  9. 修改默认input(file)的样式

    以上是默认的 <input type="file" > 但是丑爆了啊同志们~~长久以来都是调用大神的代码,今天我也小试牛刀,做出了如下效果: 这样还是能接受的样子啦~ ...

  10. NOIP2016 DAY2 T1 组合数问题

    题目描述 组合数表示的是从n个物品中选出m个物品的方案数.举个例子,从(1,2,3) 三个物品中选择两个物品可以有(1,2),(1,3),(2,3)这三种选择方法.根据组合数的定 义,我们可以给出计算 ...