123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- # -*- coding: utf-8 -*-
- """
- Created on 2021/3/18 4:59 下午
- ---------
- @summary:
- ---------
- @author: Boris
- @email: boris_liu@foxmail.com
- """
- import queue
- import threading
- from feapder.utils.log import log
- from feapder.utils.tools import Singleton
- from feapder.utils.webdriver.selenium_driver import SeleniumDriver
- @Singleton
- class WebDriverPool:
- def __init__(
- self, pool_size=5, driver_cls=SeleniumDriver, thread_safe=False, **kwargs
- ):
- """
- Args:
- pool_size: driver池的大小
- driver: 驱动类型
- thread_safe: 是否线程安全
- 是则每个线程拥有一个driver,pool_size无效,driver数量为线程数
- 否则每个线程从池中获取driver
- **kwargs:
- """
- self.pool_size = pool_size
- self.driver_cls = driver_cls
- self.thread_safe = thread_safe
- self.kwargs = kwargs
- self.queue = queue.Queue(maxsize=pool_size)
- self.lock = threading.RLock()
- self.driver_count = 0
- self.ctx = threading.local()
- @property
- def driver(self):
- if not hasattr(self.ctx, "driver"):
- self.ctx.driver = None
- return self.ctx.driver
- @driver.setter
- def driver(self, driver):
- self.ctx.driver = driver
- @property
- def is_full(self):
- return self.driver_count >= self.pool_size
- def create_driver(self, user_agent: str = None, proxy: str = None):
- kwargs = self.kwargs.copy()
- if user_agent:
- kwargs["user_agent"] = user_agent
- if proxy:
- kwargs["proxy"] = proxy
- return self.driver_cls(**kwargs)
- def get(self, user_agent: str = None, proxy: str = None):
- """
- 获取webdriver
- 当webdriver为新实例时会使用 user_agen, proxy, cookie参数来创建
- Args:
- user_agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36
- proxy: xxx.xxx.xxx.xxx
- Returns:
- """
- if not self.is_full and not self.thread_safe:
- with self.lock:
- if not self.is_full:
- driver = self.create_driver(user_agent, proxy)
- self.queue.put(driver)
- self.driver_count += 1
- elif self.thread_safe:
- if not self.driver:
- driver = self.create_driver(user_agent, proxy)
- self.driver = driver
- self.driver_count += 1
- if self.thread_safe:
- driver = self.driver
- else:
- driver = self.queue.get()
- return driver
- def put(self, driver):
- if not self.thread_safe:
- self.queue.put(driver)
- def remove(self, driver):
- if self.thread_safe:
- if self.driver:
- self.driver.quit()
- self.driver = None
- else:
- driver.quit()
- self.driver_count -= 1
- def close(self):
- if self.thread_safe:
- log.info("暂不支持关闭需线程安全的driver")
- while not self.queue.empty():
- driver = self.queue.get()
- driver.quit()
- self.driver_count -= 1
|