爬取徽州建築的,後期用於徽州建築的分類處理。
解析機器定時向排程器傳送訊息,告訴排程器自己當前處理了多少任務,排程器根據解析器處理的任務數,向解析器的佇列傳送對應量的url資料。整個大環境下,排程器與解析器形成生產者消費者佇列;小環境下,解析器自己有生產者阻塞佇列,消費者執行緒池。
好處:根據不同機器當前處理任務的能力去分發任務。
缺點:socket過程耗時。
為什麼要用排程器?
主要是為了防止不同機器不同執行緒的高併發請求資料庫帶來的事務的碰撞,導致資料庫處理速度變慢。通過排程器乙個機器獲取資料,分發給處理器的方式,可以使得資料操作變快。
執行緒池的實現中,當佇列滿時會呼叫構造時傳入的rejectedexecutionhandler去拒絕任務。預設的實現是abortpolicy,直接丟擲乙個rejectedexecutionexception。
四種拒絕策略:
abortpolicy 丟棄任務,拋執行時異常
discardoldestpolicy 工作佇列頭部的任務會被踢出佇列,然後重試執行程式
discardpolicy也是丟棄任務,只不過他不丟擲異常。
callerrunspolicy 執行任務,這個策略是不想放棄執行任務。但是由於池中已經沒有任何資源了,那麼就直接使用呼叫該execute的執行緒本身來執行
這裡和我們的需求比較接近的是callerrunspolicy,這種策略會在佇列滿時,讓提交任務的執行緒去執行任務,相當於讓生產者臨時去幹了消費者幹的活兒,這樣生產者雖然沒有被阻塞,但提交任務也會被暫停。
但這樣也不能完成我們的需求,我們的需求是,當執行緒池任務佇列滿的時候,不再接受任務。最簡單的做法,我們可以直接定義乙個rejectedexecutionhandler,當佇列滿時改為呼叫blockingqueue.put來實現生產者的阻塞:
new rejectedexecutionhandler() catch (interruptedexception e) }}
};
這就無需再關心解析器任務佇列和執行緒池的邏輯,只管往執行緒池提交任務就行了。
解析器處理器為i7四核,每個執行緒等待html的時間設定為1s,每個html的解析時間大約0.5秒,最大核心執行緒數=(0.5+1)/0.5*4=12。
設定每個解析器最大核心執行緒數為12個。
通過將資料庫中的url設定為hash索引,判斷url是否已經爬取到。
這種速度很慢,但實現簡單,速度上也不算很慢,但要是資料量再大,可以考慮使用hashset做查重過濾。資料量再大,到億級資料,hashset會溢位記憶體時,可以考慮使用布隆過濾器。
使用開源包jsoup做頁面解析。網頁中有包含想要查詢的關鍵字:如徽州,馬頭牆,房簷等,則認為該頁面是有價值頁面,將url放入資料庫,並將對應的關鍵字一同儲存,後期分類做標記資料使用。
從搜尋引擎中找到有關徽州建築的前20個網頁,從這些網頁作為入口,從網頁中往下一層一層爬取。
使用mysql集群,主從複製,讀寫分離,降低讀寫在同乙個資料庫中造成的不必要的事務的處理。
執行緒池在沒有自定義拒絕策略時,無法用乙個比較優秀的方法,使得執行緒池滿的時候,停止往內部插入任務。不管是使用自帶的fixedthreadpool還是cachedthreadpool,亦或者通過threadpoolexecutor直接建立,都不能很好的解決任務一直插入的問題。
最先想到的解決方案是等待執行緒池中任務執行結束(使用計數器判斷運**況),再向排程器請求資料(100個)。這樣導致執行效率很低,通常需要一群執行緒等待乙個執行緒執行結束,才可以進行下一步,而且會有佇列中空期,這個期間沒有任何任務在執行。後來對每個執行緒執行時間做設定,每個請求只等待1s,沒有資料返回,直接拋棄url,這樣速度稍有提公升,但會誤傷很多在等一下就可以獲取的資料。
最後通過自定義任務拒絕策略完成最終版本,這個版本中解析器中一直有任務在處理,排程器會根據當前機器處理的快慢發布不同數量的url,達到初步的負載均衡。
編寫java多執行緒爬蟲程式
所謂爬蟲程式,就是模擬瀏覽器傳送http請求給web 這裡我們實現乙個這樣的爬蟲程式 列出segmentfault 中指定使用者所有文章及其閱讀人數的程式 基本思路是這樣的 1我們進入某使用者的文章列表頁 2獲得文章列表 3對文章逐個訪問 4獲取文章頁面的閱讀數 比如以我的主頁舉例 1 進入文章列表...
爬蟲多執行緒
多執行緒在之前的scrapy裡面已經接觸過了,就是裡面的yiled,開啟乙個新的執行緒。但是這是這是基於這個高階框架的,用的時候只知道這是開啟了乙個新的執行緒,並不是很清楚到底是怎麼執行的。而在python裡面有包 import threading引入這個包之後就可以寫自己的多執行緒了 寫多執行緒的...
多執行緒爬蟲
python標準庫是執行緒之間常見的資料交換形式 queue的使用可以確保python的執行緒安全 q queue.queue maxsize 建立佇列,並可以指定大小 q.empty 判斷佇列是否為空 q.full 判斷佇列是否滿 q.put data 向佇列中放入資料 q.get 從佇列中拿資料...