05 Python 爬蟲教學10 所有文章

【爬蟲教學】如何讓 Selenium 多線池執行時 driver 不會重複開啟

python_selenium_driver

本篇主要紀錄使用 Selenium 搭配 Multi-threading Pool (多執行緒池/多線程池) 遇到 web driver 會重複開啟和關閉的問題,導致效率大幅下降,解決方法是使用 threading.local 將 driver 變數存 local 來判斷是否有需要重複開啟

使用 threading.local()

利用 threading.local() 的方法將 driver 變數存在 thread 線程內,當每次 thread 線程重新執行時會先 getattr 看看有無 driver 沒有的話就會重新開啟。

import threading

threadLocal = threading.local()

def get_driver():
driver = getattr(threadLocal, 'driver', None)
if driver is None:
chromeOptions = webdriver.ChromeOptions()
chromeOptions.add_argument("--headless")
driver = webdriver.Chrome(chrome_options=chromeOptions)
setattr(threadLocal, 'driver', driver)
return driver


def get_title(url):
driver = get_driver()
driver.get(url)

if __name__ == '__main__':
url_list = ["A","B","C"]
ThreadPool(5).map(get_title,url_list)

當執行噴錯時,可以在 except 內把 driver 關閉,並輸入 setattr(self.threadLocal, ‘driver’, None),這樣下次執行時就會自動再開啟新的 driver 了

try:

  "do something"

except TimeoutException as e:
  driver.close()
  setattr(self.threadLocal, 'driver', None)
  time.sleep(10)
  break

如何在執行完所有線程池時,再將目前有開啟的 driver 關閉?如果直接在 finally 的地方寫下 driver.close() 或 driver.quit(),你會發現他會找不到指定的 driver,所以會無法將所有的 driver 關閉乾淨。

所以我是當有建立 driver 的時候,就將 driver 存入 driver_log 這個 list 內,當執行結束時再用迴圈將所有 list 內的 driver 關閉。

self.driver_log = []

for a in self.driver_log:
try:
a.close()
a.quit()
except:
pass

最後~

▍關於 Selenium 相關其他文章,可以參考:

▍關於與 Concurrency Programming 相關其他文章,可以參考:

▍關於 Async IO 相關其他文章,可以參考:

那麼有關於【爬蟲教學】如何讓 Python selenium 多線池執行時 driver 不會重複開啟 的介紹就到這邊告一個段落囉!有任何問題可以在以下留言~

有關 Max行銷誌的最新文章,都會發佈在 Max 的 Facebook 粉絲專頁,如果想看最新更新,還請您按讚或是追蹤唷!

在《【爬蟲教學】如何讓 Selenium 多線池執行時 driver 不會重複開啟》中有 2 則留言

  1. 請問最後哪裏把driver全放到一個list裏應該怎麽寫呢?不大明白。是自定義了一個類?不知道可不可以說詳細點/公開更完整的代碼呢?謝謝!

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *