网络爬虫:采用“负载均衡”策略来优化网络爬虫
前言:
? 這里說的負載均衡并非大家熟悉的網絡中的負載均衡。
? 只是這里我使用了和負載均衡同樣的一種思維來優化程序罷了,其實就是壓力分攤。
問題描述:
? 對于上一篇《分離生產者和消費者來優化爬蟲程序》博客中遺留的問題:線程阻塞。
? 當我們的程序運行到一定時間之后,會出現線程池中的500條線程不夠用的情況,進而程序長期處于等待的狀態。
壓力測試實驗:
? 本實驗基于之前的爬蟲程序,線程池中的線程最大為320條。下面是對在主線程中以不同時間間隔執行程序的測試結果:
sleep 300ms
sleep 500ms
sleep 1000ms
內存使用狀態圖:
代碼優化邏輯:
1.python代碼優化
import sys reload(sys) sys.setdefaultencoding('utf8') from time import clock, sleep import threadingfrom list_web_parser import ListWebParser import get_html_response as gethdef visited_html(html):myp = ListWebParser()get_html = geth.get_html_response(html)myp.feed(get_html)link_list = myp.getLinkList()myp.close()for item in link_list:if item[0] and item[1]:print item[0], '$#$', item[1]global thread_done_flagthread_done_flag = Truedef count_down():start = clock()while True:sleep(1)end = clock()if int(end - start) >= 2:print 'TIME OUT'global thread_done_flagthread_done_flag = Truebreakthread_done_flag = Falsedef start_work(url):thread1 = threading.Thread(target=visited_html, args=(url,))thread2 = threading.Thread(target=count_down)thread1.setDaemon(True)thread2.setDaemon(True)thread1.start()thread2.start()while not thread_done_flag:''if __name__ == "__main__":if not sys.argv or len(sys.argv) < 2:print 'You leak some arg.'start_work(sys.argv[1])? 這段代碼做了一件事,主線程跟隨第一個子線程結束而結束。
? 目的是為了讓程序在1秒鐘之內結束運行,而超過1秒的html解析,我們將拋棄。我想這是合理的。因為我們不可能讓Python一直占用我們的線程資源,這樣很快線程就會出現阻塞。而且,隨著我們解析HTML的線程數的增加。CPU的消耗也很快,這樣我們的計算機就會出現卡頓的情況。
2.Java代碼優化
public void visittingUrl(String startAddress) {// url 合法性判斷if (startAddress == null) {return;}// 種子url 入庫SpiderBLL.insertEntry2DB(startAddress);// 解析種子urlPythonUtils.fillAddressQueueByPython(mUnVisitedQueue, startAddress, 0);if (mUnVisitedQueue.isQueueEmpty()) {System.out.println("Your address cannot get more address.");return;}boolean breakFlag = false;int index = 0;startThread();while (!breakFlag) {WebInfoModel model = mUnVisitedQueue.poll();if (model == null) {System.out.println("------ 此URL為NULL ------");continue;}// 判斷此網站是否已經訪問過if (DBBLL.isWebInfoModelExist(model)) {// 如果已經被訪問,進入下一次循環System.out.println("已存在此網站(" + model.getName() + ")");continue;}poolQueueFull(mThreadPool);System.out.println("LEVEL: [" + model.getLevel() + "] NAME: " + model.getName());mThreadPool.execute(new ParserRunner(mResultSet, model, index++, mResultMap));SystemBLL.cleanSystem(index);// 對已訪問的address進行入庫DBBLL.insert(model);model = null;SystemBLL.sleep(300);}mThreadPool.shutdown();}? Java代碼的代碼主要體現在,我們每次調用Python進行解析HTML時,都會sleep 300毫秒。這樣我們CPU的壓力就轉移到時間上了。而這300毫秒其實對整體程序的影響不大,算是優點大于缺點吧。
關于上一篇:
1.覆蓋equals時總要覆蓋hashCode
? 我們需要覆蓋WebInfoModel的equals和hashCode方法,目的是我們把這個對象保存到HashSet中,需要保證它的唯一性。那么我們就必須自己來寫一些唯一性的策略:重寫equals方法。而重寫equals時,必須要重寫hashCode方法。關于這一點,大家可以參看筆者的另一篇博客《Effective Java:對于所有對象都通用的方法》
@Overridepublic int hashCode() {return (name.hashCode() + address.hashCode() + level);}@Overridepublic boolean equals(Object obj) {if (!(obj instanceof WebInfoModel)) {return false;}if (((WebInfoModel)obj).getName() == name && ((WebInfoModel)obj).getAddress() == address && ((WebInfoModel)obj).getLevel() == level) {return true;}return false;}
遺留的問題:
1.python無故停止運行
下一步的目標:
1.解決python程序停止運行的Bug
2.分布式
(終于,終于可以開始利用分布式來優化我的蜘蛛程序了。想想還有一點小激動呢 ^_^)
總結
以上是生活随笔為你收集整理的网络爬虫:采用“负载均衡”策略来优化网络爬虫的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网络爬虫:分离生产者和消费者来优化爬虫程
- 下一篇: 网络爬虫:URL去重策略之布隆过滤器(B