本篇主要紀錄使用 Selenium 搭配 Multi-threading Pool (多執行緒池/多線程池) 遇到 web driver 會重複開啟和關閉的問題,導致效率大幅下降,解決方法是使用 threading.local 將 driver 變數存 local 來判斷是否有需要重複開啟
使用 threading.local()
利用 threading.local() 的方法將 driver 變數存在 thread 線程內,當每次 thread 線程重新執行時會先 getattr 看看有無 driver 沒有的話就會重新開啟。
1 |
import threading<br><br>threadLocal = threading.local()<br><br>def get_driver():<br> driver = getattr(threadLocal, 'driver', None)<br> if driver is None:<br> chromeOptions = webdriver.ChromeOptions()<br> chromeOptions.add_argument("--headless")<br> driver = webdriver.Chrome(chrome_options=chromeOptions)<br> setattr(threadLocal, 'driver', driver)<br> return driver<br><br><br>def get_title(url):<br> driver = get_driver()<br> driver.get(url)<br><br>if __name__ == '__main__':<br> url_list = ["A","B","C"]<br> ThreadPool(5).map(get_title,url_list) |
當執行噴錯時,可以在 except 內把 driver 關閉,並輸入 setattr(self.threadLocal, ‘driver’, None),這樣下次執行時就會自動再開啟新的 driver 了
1 |
try:<br><br> "do something"<br><br>except TimeoutException as e:<br> driver.close()<br> setattr(self.threadLocal, 'driver', None)<br> time.sleep(10)<br> break |
如何在執行完所有線程池時,再將目前有開啟的 driver 關閉?如果直接在 finally 的地方寫下 driver.close() 或 driver.quit(),你會發現他會找不到指定的 driver,所以會無法將所有的 driver 關閉乾淨。
所以我是當有建立 driver 的時候,就將 driver 存入 driver_log 這個 list 內,當執行結束時再用迴圈將所有 list 內的 driver 關閉。
1 |
self.driver_log = []<br><br>for a in self.driver_log:<br> try:<br> a.close()<br> a.quit()<br> except:<br> pass |
最後~
▍關於 Selenium 相關其他文章,可以參考:
- 【爬蟲教學】Python Selenium 爬蟲教學:實作商品庫存爬取
- 【爬蟲教學】如何在 GCP 上架設 selenium 爬蟲環境
- 【爬蟲筆記】Python Selenium Webdriver異常問題集
▍關於與 Concurrency Programming 相關其他文章,可以參考:
- 【【Python教學】淺談 Concurrency Programming
- 【Python教學】淺談 GIL & Thread-safe & Atomic
- 【Python教學】淺談 Multi-processing & Multi-threading 使用方法
- 【Python教學】淺談 Multi-processing pool 使用方法
▍關於 Async IO 相關其他文章,可以參考:
- 【Python教學】淺談 Coroutine 協程使用方法
- 【Python教學】Async IO Design Patterns 範例程式
- 【實戰篇】 解析 Python 之父寫的 web crawler 異步爬蟲
那麼有關於【爬蟲教學】如何讓 Python selenium 多線池執行時 driver 不會重複開啟 的介紹就到這邊告一個段落囉!有任何問題可以在以下留言~
有關 Max行銷誌的最新文章,都會發佈在 Max 的 Facebook 粉絲專頁,如果想看最新更新,還請您按讚或是追蹤唷!
在〈【爬蟲教學】如何讓 Selenium 多線池執行時 driver 不會重複開啟〉中有 3 則留言
請問最後哪裏把driver全放到一個list裏應該怎麽寫呢?不大明白。是自定義了一個類?不知道可不可以說詳細點/公開更完整的代碼呢?謝謝!
HI,
代碼是跟專案綁在一起,需要點時間清理,到粉專留個言,我清理完私訊給你
非常棒. threadLocal是个好方法.