檢索百張的頁面,爬蟲運行下來往往在一小時以內,時間上還是可以接受的。但當整理后的URL數量過多的時候,就只能考慮采取多線程分步爬取了。Python里控制多線程只需要用到模板threading,而且只需要用到其中的Thread。
簡單的使用方法如下:
1 import time 2 import threading 3 4 def spider(number): 5 print u"%d 號爬蟲開始運行! 時間: %s" % (number,time.strftime('%H:%M:%S',time.localtime())) 6 time.sleep(2) 7 print u"%d 號爬蟲運行結束! 時間: %s" % (number,time.strftime('%H:%M:%S',time.localtime())) 8 9 if __name__ == "__main__": 10 thread = 5 11 print u"主程序開始運行! 時間: %s" % time.strftime('%H:%M:%S',time.localtime()) 12 for i in range(1,thread+1): 13 t = threading.Thread(target=spider,args=(i,)) 14 t.start() 15 16 print u"主程序運行結束! 時間: %s" % time.strftime('%H:%M:%S',time.localtime())
Thread使用方法為:
threading.Thread(target=線程運行的函數,args=(參數)) 其中參數用逗號分隔,並以逗號結尾。
隨后使用start啟動。
運行結果如下:

可以看到五個線程同步運行,因sleep設置的時間相同,所以也同步結束。
但有一個缺點是第16行代碼在五個線程啟動后隨即也就運行了,相當於此時主線程已經結束了而那五個子線程還在運行。
控制策略有兩個
在start之前把子線程設置為守護線程
修改代碼如下:
1 for i in range(1,thread+1): 2 t = threading.Thread(target=spider,args=(i,)) 3 t.setDaemon(True) 4 t.start()
運行結果如下:

子線程在主線程結束的時候也同步結束,未運行的部分也就不再運行了。
在主線程中使用join,讓主線程掛起等待子線程結束
修改代碼如下:
1 for i in range(1,thread+1): 2 t = threading.Thread(target=spider,args=(i,)) 3 t.start() 4 t.join()

從運行結果可以看到主線程停留在t.join()的位置,一直等到五個子線程全部結束后才開始繼續向后運行。
以上就是需要用到的threading模板里所有的東西了。
在整理好需要處理的數據列表后,我們只需要將列表分段分別交給不同的線程來處理,主線程等待所有數據處理完畢之后再進行下一步操作,如下:
1 import time 2 import threading 3 4 def spider(number,data_list): 5 print u"%d 號爬蟲開始運行! 時間: %s" % (number,time.strftime('%H:%M:%S',time.localtime())) 6 print u"%d 號爬蟲需要處理的數據有%s ! 時間: %s" % (number,str(data_list),time.strftime('%H:%M:%S',time.localtime())) 7 time.sleep(2) 8 print u"%d 號爬蟲運行結束! 時間: %s" % (number,time.strftime('%H:%M:%S',time.localtime())) 9 10 if __name__ == "__main__": 11 thread = 5 12 ls = [] 13 ls2 = [] 14 for n in range(1,58): 15 ls.append(n) 16 length = len(ls)//thread+1 17 for m in range(thread): 18 ls2.append(ls[length*m:length*m+length]) 19 20 print u"主程序開始運行! 時間: %s" % time.strftime('%H:%M:%S',time.localtime()) 21 for i in range(1,thread+1): 22 t = threading.Thread(target=spider,args=(i,ls2[i-1],)) 23 t.start() 24 t.join() 25 print u"主程序運行結束! 時間: %s" % time.strftime('%H:%M:%S',time.localtime())
運行結果如下:

五個線程分步處理各自被分配到的數據,總體運行時間大幅縮減。當然機器給力的話,可以增加線程數,得到更快的速度。
