所以我們的多執行緒在程式是怎麼運作呢?
一般情況:
送出
到收到資料
皆須花費三秒
。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...")
輸出(圖片橫幅太寬,我截圖只截一半請見諒):
以上就是多執行緒搭配爬蟲的應用!可以依照不同需求再自行修改~