该事例演示了如何在多线程中统计和分析数据;
首先建一个状态实体类CrawlStat:
package com.java1234.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.java1234.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.zuidaima.com"); // 必须是java1234域名
}
/**
* 当我们爬到我们需要的页面,这个方法会被调用,我们可以尽情的处理这个页面
* 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.java1234.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.zuidaima.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.zuidaima.com/ 正在爬取页面:http://www.zuidaima.com/share/2814499085634560.htm 正在爬取页面:http://www.zuidaima.com/share/2519215530527744.htm 正在爬取页面:http://www.zuidaima.com/share/2783070349888512.htm 当前爬虫实例id:2 总处理页面:3 总链接长度:672 总文本长度:22295 正在爬取页面:http://www.zuidaima.com/share/2769260213275648.htm 正在爬取页面:http://www.zuidaima.com/share/kredis-p1-s1.htm 正在爬取页面:http://www.zuidaima.com/share/kswing-p1-s1.htm 当前爬虫实例id:2 总处理页面:6 总链接长度:1299 总文本长度:46674 正在爬取页面:http://www.zuidaima.com/share/kcodehaus-p1-s1.htm 正在爬取页面:http://www.zuidaima.com/user/2176279510861824.htm 正在爬取页面:http://www.zuidaima.com/blog/2881413902666752.htm 当前爬虫实例id:2 总处理页面:9 总链接长度:1617 总文本长度:90618 当前爬虫实例id:1 总处理页面:1 总链接长度:326 总文本长度:10321 当前爬虫实例id:2 总处理页面:9 总链接长度:1617 总文本长度:90618 统计数据: 总处理页面:10 总链接长度:1943 总文本长度:100939
上一篇:crawler4j处理单个页面
下一篇:crawler4j多线程爬虫实例