所以我們的多執行緒在程式是怎麼運作呢?
一般情況:
送出到收到資料皆須花費三秒。import time
def req1():
    print("req1: 開始送 request") 
    time.sleep(3)
    print("req1: 接收到 response") 
def req2():
    print("req2: 開始送 request") 
    time.sleep(3)
    print("req2: 接收到 response")
if __name__ == '__main__':
    req1()
    req2()
輸出:

我們可以運用多執行緒:
import time
# import python 的多執行緒套件
from threading import Thread
def req1():
    print("req1: 開始送 request") 
    time.sleep(3)
    print("req1: 接收到 response") 
def req2():
    print("req2: 開始送 request") 
    time.sleep(3)
    print("req2: 接收到 response")
if __name__ == '__main__':
    # 先將 funtion 包裝成 thread 的物件,再執行
    Thread(target=req1).start()
    Thread(target=req2).start()
輸出:

根據輸出結果我們發現到:
req1 還沒執行完就馬上接著做 req2 了!終於不用再等 req1 整個流程(function 裡的那些動作)跑完才做下一個動作了。簡單來說,程式(main)的運行就不會阻塞在那邊,會繼續往下做。根據下面的比較圖,花費時間真的變少了!
一般情況花費時間:
使用多執行緒花費時間:
而當要送出多個 request 時,會建議使用多執行緒來做,是因為 request 送出到收到 response 這中間多多少少都是要等的,而且根據現實的網路狀況,也不能保證每次都很快,可能0.3秒、5秒、10秒。所以與其等,我不如先送其他 request 來節省時間。
那我們拿之前教的個股日成交資訊結合多執行緒,來抓取多個個股日成交資訊吧!
示範:
import time
import requests
from threading import Thread
# 將流程先用 function 封裝起來,接下來才能帶入 thread 中
def daily_price_req(date, stock_no):
    res = requests.get("https://www.twse.com.tw/exchangeReport/STOCK_DAY",
                       params={
                           "response": "json",
                           "date": date,
                           "stockNo": stock_no
                       })
    # 把 JSON 轉成 Python 可存取之型態
    res_json = res.json()
    # 我們要的每日成交資訊在 data 這個欄位
    daily_price_list = res_json['data']
    # 印出資料
    print("{} 每日成交資訊: {}".format(stock_no, daily_price_list))
if __name__ == '__main__':
    # 日期什麼的,可以依照需求設定
    req_info_list = [
        {
            "date": "20211011",
            "stockNo": "2330"
        },
        {
            "date": "20211011",
            "stockNo": "2603"
        },
        {
            "date": "20211011",
            "stockNo": "2609"
        }
    ]
    for req_info in req_info_list:
        req_date = req_info.get("date")
        req_stock_no = req_info.get("stockNo")
        if req_date and req_stock_no:
            # args 為 function 會用到的參數
            req_thread = Thread(target=daily_price_req,
                                args=(req_date, req_stock_no))
            req_thread.start()
            # 每個 req 間隔最好 3 秒以上,不然會被證交所鎖 IP 一段時間
            time.sleep(3)
輸出(圖片橫幅太寬,我截圖只截一半請見諒):
多執行緒的另外一個用法:
req_thread_list = []
for req_info in req_info_list:
        req_date = req_info.get("date")
        req_stock_no = req_info.get("stockNo")
        if req_date and req_stock_no:
            req_thread = Thread(target=daily_price_req,
                                args=(req_date, req_stock_no))
            req_thread.start()
            req_thread_list.append(req_thread)
            # 每個 req 間隔最好 3 秒以上,不然會被證交所鎖 IP 一段時間
            time.sleep(3)
for req_thread in req_thread_list:
    # join() 就是讓程式等著,確定該 thread 已經執行完畢之後再繼續往下
    # 所以這邊的用法是說:
    # 我的程式會在這邊等所有 req thread(daily_price_req 裡的那些動作)都執行完畢後再往下做
    req_thread.join()
# do something...
print("do something...")
輸出(圖片橫幅太寬,我截圖只截一半請見諒):
以上就是多執行緒搭配爬蟲的應用!可以依照不同需求再自行修改~