摘要:實際運行中就發現了一個有趣的現象。爬蟲抓取的速度超過了我用給它推送的速度,導致爬蟲從獲取不到同時此刻線程池所有線程都已停止。如何管理設置,避免返回,且沒有工作線程時退出循環。退出檢測循環說明結束了,手動調用來是退出調度循環,終止爬蟲。
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池化,也可以采用這個思路來。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/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...
閱讀 2980·2021-11-16 11:45
閱讀 5124·2021-09-22 10:57
閱讀 1763·2021-09-08 09:36
閱讀 1585·2021-09-02 15:40
閱讀 2508·2021-07-26 23:38
閱讀 1184·2019-08-30 15:55
閱讀 923·2019-08-30 15:54
閱讀 1213·2019-08-29 14:06