1. 程式人生 > >【Python3.6爬蟲學習記錄】(十四)多執行緒爬蟲模板總結

【Python3.6爬蟲學習記錄】(十四)多執行緒爬蟲模板總結

前言:這幾天忙活的做個網頁玩玩,網上也沒有教程。買個域名又得解析,又得備案,真是麻煩,覺得一個簡單的HTML網頁應該用不到那麼麻煩吧。
昨天又看了幾個關於多執行緒爬蟲的例子,覺得很好,提煉出來,總結幾個應用模板。

目錄

一 多執行緒Threading模組

1-1 簡單的函式建立多執行緒

## 簡單應用thread模組
import socket
import threading
import requests

tasks = []
lock = threading.Lock()  # 建立一個鎖

# 執行緒工作函式
def worker(i):
    socket.setdefaulttimeout(5
) # 設定全域性超時時間 try: r = requests.get(url) lock.acquire() # 獲得鎖 print('Processing ',i) lock.release() # 釋放鎖 except Exception as e: lock.acquire() print(e) lock.release() # 多執行緒 threads = [] for i in range(len(tasks)): # 引數包括,目標函式,以及操作物件序號
thread = threading.Thread(target=worker, args=[i]) # 將全部IP加入執行緒,並開始多執行緒 threads.append(thread) thread.start() # 阻塞主程序,等待所有子執行緒結束 # 通俗的將,就是執行完上述的過程再結束 for thread in threads: thread.join()

2-1 用類包裝執行緒物件

import threading
import time

class myThread(threading.Thread):
    '''
    構造方法
    '''
def __init__(self, threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): print("Starting " + self.name) '''開啟網頁以及查詢等操作 ''' # 獲得鎖,成功獲得鎖定後返回True # 可選的timeout引數不填時將一直阻塞直到獲得鎖定 # 否則超時後將返回False threadLock.acquire() '''儲存檔案,列印操作 ''' print(self.name, self.counter, 3) # 釋放鎖 threadLock.release() threadLock = threading.Lock() threads = [] '''建立,開始,新增執行緒組 ''' for i in range(1,3): # 建立新執行緒 thread = myThread(i, "Thread-%s"%i, i) # 開啟新執行緒 thread.start() # 新增執行緒到執行緒列表 threads.append(thread) # 等待所有執行緒完成 for t in threads: t.join() print("iting Main Thread")

二 多執行緒Queue模組

2-1 使用Queue 與 Threading模組

import os
import random
import threading
import time
from queue import Queue
import requests

class myThread(threading.Thread):
    def __init__(self,func):
        # 呼叫父類建構函式
        super(myThread, self).__init__()
        # 傳入執行緒函式邏輯
        self.func=func
    def run(self):
        '''
         重寫run方法
        '''
        self.func()

# 功能函式
def worker():
    global Q
    while not Q.empty():
        # 獲得任務
        item = Q.get()
        '''
        執行的任務
        '''
        # 原來寫Queue,沒有初始化
        Q.task_done()

'''其他功能性函式
'''

# 主函式
def main():
    global Q
    threads = []
    # 向佇列中放入任務
    for task in range(len(tasks)):
        Q.put(tasks[task])
    # 執行執行緒
    for i in range(thread_num):
        thread = myThread(worker)
        thread.start()
        threads.append(thread)
    # 等待執行緒結束
    for thread in threads :
        thread.join()
    # 等待所有執行緒結束
    Q.join()
# 本專案中執行
if __name__ == '__main__':
    # 無限制佇列
    Q = Queue()
    # 執行緒數
    thread_num = 100
    # 任務物件列表
    tasks = []
    start = time.time()
    main()
    end = time.time()
    print('It takes ',end-start)

三 多程序併發模組

3-1 Queue 與 Threading實現併發

# 多執行緒併發模板
from queue import Queue
from threading import Thread
from time import sleep
#q是任務佇列
#NUM是併發執行緒總數
#JOBS是有多少任務
q = Queue()
NUM = 2
JOBS = 10

#具體的處理函式,負責處理單個任務
def do_somthing_using(arguments):
    print(arguments)

#這個是工作程序,負責不斷從佇列取資料並處理
def working():
    while True:
        arguments = q.get()
        do_somthing_using(arguments)
        sleep(1)
        q.task_done()

#fork NUM個執行緒等待佇列
for i in range(NUM):
    t = Thread(target=working)
    t.setDaemon(True)
    t.start()

#把JOBS排入佇列
for i in range(JOBS):
    q.put(i)

#等待所有JOBS完成
q.join()

3-2 multiprocessing模組實現併發

from multiprocessing import Pool
pool = Pool(8)
data_list = pool.map(get, url_list)
pool.close()
pool.join()

後記:
有些並不是很理解,但是可以直接套模板。簡單簡單點來,可以用類包裝Threading模組,但是如果應用物件很多,這樣一下子把所有的執行緒都開了,會卡死,應該有解決辦法吧,目前還沒查到;然後,如果任務物件很多,就直接用queue模組,只開啟一定的執行緒,依次執行,目前應用的蠻好,再看;最後,關於多程序併發的還不是很清楚,之後在瞭解吧。期間還看到了協程,等知識不夠用了再學。