WebCollect爬虫 之Fetcher 抓取器解析
上一篇写了WebCollect的核心类Crawer知道了爬虫启动过程
这篇编写Fetcher 抓取器解析
// dbManager 数据Url 管理器 ,由Crawer set
public DBManager dbManager;
// 实际 从datum 中获取数据并处理,下一个任务, 由Crawer set
public Executor executor;
// 下一个任务URL 的过滤器, 由Crawer set
public NextFilter nextFilter = null;
// 活跃线程数, 并发安全
private AtomicInteger activeThreads;
// 已启动线程数 并发安全
private AtomicInteger startedThreads;
private AtomicInteger spinWaiting;
// 最后请求的时间戳 并发安全
private AtomicLong lastRequestStart;
// 向任务队列里放任务的Runnable Thread
private QueueFeeder feeder = null;
// 任务队列, 并发安全,
private FetchQueue fetchQueue = null;
// 抓取线程数 ,由Crawer set
private int threads = 50;
其 抓取过程,
1.判断实际执行器
2.初始化dbManager
3.设置初始信息.
4.启动向任务队列中插入任务线程.
5.启动任务线程
6.监控任务 最后请求时间,如果间隔大于配置的ThreadKiller 则 挂起任务线程,
等待存活线程配置的WaitThreadEndTime 时间后停止任务线程,终止任务.
/**
* 抓取当前所有任务,会阻塞到爬取完成
*
* @throws IOException 异常
*/
public int fetchAll(GeneratorFilter generatorFilter) throws Exception {
// 首先如果实际通过datum URL 获取网页内容的执行器为null 返回
if (executor == null) {
LOG.info("Please Specify A Executor!");
return 0;
}
dbManager.merge();
try {
// 初始化写
dbManager.initSegmentWriter();
LOG.info("init segmentWriter:" + dbManager.getClass().getName());
running = true;
// 设置初始信息
lastRequestStart = new AtomicLong(System.currentTimeMillis());
activeThreads = new AtomicInteger(0);
startedThreads = new AtomicInteger(0);
spinWaiting = new AtomicInteger(0);
// 任务队列
fetchQueue = new FetchQueue();
// 向任务队列中插入任务datum 的线程,最大队列长队为1000, 这个固定1000, 不知作者有什么依据没,开启线程
feeder = new QueueFeeder(fetchQueue, dbManager, generatorFilter, 1000);
feeder.start();
// 这里 任务线程启动
FetcherThread[] fetcherThreads = new FetcherThread[threads];
for (int i = 0; i < threads; i++)<