摘要:实际运行中就发现了一个有趣的现象。爬虫抓取的速度超过了我用给它推送的速度,导致爬虫从获取不到同时此刻线程池所有线程都已停止。如何管理设置,避免返回,且没有工作线程时退出循环。退出检测循环说明结束了,手动调用来是退出调度循环,终止爬虫。
Webmagic源码分析系列文章,请看这里
从解决问题开始吧。
问题描述:由于数据库的数据量特别大,而且公司没有搞主从读写分离,导致从数据库读取数据比较慢,而我需要从数据库查询出特定标识来拼url去抓。实际运行中就发现了一个有趣的现象。爬虫抓取的速度超过了我用scheduler给它推送url的速度,导致爬虫从scheduler获取不到url,同时此刻线程池所有线程都已停止。这个时候,根据Spider的机制是要退出调度循环的,从而终止Spider。从下面代码可以看出:(取自Spider的run方法):
while ((!(Thread.currentThread().isInterrupted())) && (this.stat.get() == 1)) { Request request = this.scheduler.poll(this); if (request == null) { if ((this.threadPool.getThreadAlive() == 0) && (this.exitWhenComplete)) { break; } waitNewUrl(); } else { Request requestFinal = request; this.threadPool.execute(new Runnable(requestFinal) { public void run() { try { Spider.this.processRequest(this.val$requestFinal); Spider.this.onSuccess(this.val$requestFinal); } catch (Exception e) { Spider.this.onError(this.val$requestFinal); Spider.this.logger.error("process request " + this.val$requestFinal + " error", e); } finally { Spider.this.pageCount.incrementAndGet(); Spider.this.signalNewUrl(); } } }); } } this.stat.set(2); if (this.destroyWhenExit) close();
上述中,由于Spider默认exitWhenComplete=true,而this.threadPool.getThreadAlive() == 0也在我刚刚描述的场景中应验了,所以此时Spider会break退出调度循环,进而终止。
那么如何解决呢?我们应该注意到了exitWhenComplete这个标志,Spider是开放了这个标志的setter的,那么我们可以通过它来实现自定义的管理。如何管理?
//设置exitWhenComplete=false,避免scheduler.poll返回null,且没有工作线程时退出循环。 spider.setExitWhenComplete(false); spider.start(); //分页循环推送url int i=2; while(i<=page.getTotalPages()){ page=storeManager.findPage(c, i, 50); for(Store s:page.getResult()){ if(StringUtils.isNotBlank(s.getSkipLink()) && s.getSkipLink().contains("?id=")){ Request request=new Request(s.getSkipLink()); scheduler.push(request,spider); } } i++; } int nullCount=0; //分5次重试来确保真的没有了。 while(nullCount<5){ //如果没有活动线程,我们就查看scheduler中是否有request,如果没有,计数+1,之后休眠再重新循环。 if(spider.getThreadAlive()==0){ Request req=scheduler.poll(spider); if(req==null){ nullCount++; }else{ if(nullCount>0){ nullCount=0; } scheduler.push(req, spider); } } HttpReqUtil.sleep(5*60*1000); } //退出检测循环说明结束了,手动调用stop()来是Spider退出调度循环,终止爬虫。 spider.stop();
其实,如果你想Spider池化,也可以采用这个思路来。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/69916.html
摘要:爬虫框架源码分析之爬虫框架源码分析之爬虫框架源码分析之爬虫框架源码分析之爬虫框架源码分析之之进阶 爬虫框架Webmagic源码分析之Spider爬虫框架WebMagic源码分析之Scheduler爬虫框架WebMagic源码分析之Downloader爬虫框架WebMagic源码分析之Selector爬虫框架WebMagic源码分析之SeleniumWebMagic之Spider进阶
摘要:获取正在运行的线程数,用于状态监控。之后初始化组件主要是初始化线程池将到中,初始化开始时间等。如果线程池中运行线程数量为,并且默认,那么就停止退出,结束爬虫。 本系列文章,针对Webmagic 0.6.1版本 一个普通爬虫启动代码 public static void main(String[] args) { Spider.create(new GithubRepoPageP...
摘要:包主要实现类,这是一个抽象类,实现了通用的模板方法,并在方法内部判断错误重试去重处理等。重置重复检查就是清空,获取请求总数也就是获取的。至于请求总数统计,就是返回中维护的的大小。 Scheduler是Webmagic中的url调度器,负责从Spider处理收集(push)需要抓取的url(Page的targetRequests)、并poll出将要被处理的url给Spider,同时还负责...
摘要:方法,首先判断是否有这是在中配置的,如果有,直接调用的将相应内容转化成对应编码字符串,否则智能检测响应内容的字符编码。 Downloader是负责请求url获取返回值(html、json、jsonp等)的一个组件。当然会同时处理POST重定向、Https验证、ip代理、判断失败重试等。 接口:Downloader 定义了download方法返回Page,定义了setThread方法来...
摘要:是爬虫框架中比较简单易上手的一个。官网链接下面的例子是使用这个框架来爬取工商银行的私人理财推荐分页列表数据。页面链接为引入配置如果项目已经引入记录日志,则需要在中排除。 webmagic是java爬虫框架中比较简单易上手的一个。官网链接:http://webmagic.io/ 下面的例子是使用这个框架来爬取工商银行的私人理财推荐分页列表数据。页面链接为:https://mybank.i...
阅读 2936·2021-11-16 11:45
阅读 4897·2021-09-22 10:57
阅读 1686·2021-09-08 09:36
阅读 1537·2021-09-02 15:40
阅读 2449·2021-07-26 23:38
阅读 1144·2019-08-30 15:55
阅读 895·2019-08-30 15:54
阅读 1183·2019-08-29 14:06