-
스파이더에서 크롤링을 실행할 때 스크래피에 의해 생성되는 Selenium WebDriver 인스턴스 수를 줄이는 방법은 무엇입니까?카테고리 없음 2020. 8. 20. 21:13
질문
스파이더에 대한 크롤링 프로세스를 실행할 때 Scrapy는 실행중인 스파이더가 Selenium을 사용하지 않더라도 많은 (19-30 사이의 평균 27 개) Firefox 인스턴스를 생성하는 경향이 있습니다.
Selenium을 사용하는 각 스파이더에서
def __del __ (self)
내부에서driver.quit ()
를 시도했습니다. 문제는 여전히 지속됩니다.Firefox 인스턴스는 크롤링 프로세스가 완료된 후에도 계속 열려 있습니다.
Selenium을 사용한 거미 예 :
import logging import time from os.path import abspath, dirname, join import requests import scrapy import selenium from scrapy.http import HtmlResponse from selenium import webdriver from selenium.common.exceptions import TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.firefox.options import Options from selenium.webdriver.remote.remote_connection import LOGGER from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait LOGGER.setLevel(logging.ERROR) PATH_DIR = dirname(abspath(__file__)) GECKODRIVER_PATH = abspath(join(PATH_DIR, "../../geckodriver")) WAIT_TIME = 10 class ExampleSpider(sso_singapore.SsoSpider): name = "Example" options = Options() options.headless = True driver = webdriver.Firefox(options=options, executable_path=GECKODRIVER_PATH) def __del__(self): self.driver.quit() def parse(self, response): meta = response.meta try: self.driver.get(response.url) body = self.driver.page_source try: element = WebDriverWait(self.driver, WAIT_TIME).until( EC.presence_of_element_located( (By.ID, '//select[@id="rows_sort"]/option[text()="All"]') ) ) except: pass response = HtmlResponse( self.driver.current_url, body=body, encoding="utf-8" ) except Exception as e: logging.error(str(e)) finally: self.driver.quit() # Create Items based on response def start_requests(self): for url, meta in zip(urls, meta_list): yield scrapy.Request(url, callback=parse, meta=meta)
어떤 도움이라도 대단히 감사하겠습니다.
답변1
from scrapy import signals class ExampleSpider(sso_singapore.SsoSpider): def __init__(self, *args, **kwargs): options = Options() options.headless = True self.driver = webdriver.Firefox(options=options, executable_path="your_path") @classmethod def from_crawler(cls, crawler, *args, **kwargs): spider = super(ExampleSpider, cls).from_crawler(crawler, *args, **kwargs) crawler.signals.connect(spider.spider_closed, signal=signals.spider_closed) return spider def spider_closed(self, spider): self.driver.quit()
이것은 일을해야합니다.
Scrapy 신호에 대한 추가 정보 :
https://docs.scrapy.org/en/latest/topics/signals.html
스파이더가 많고 동일한
driver.quit ()
로직을 추가하지 않으려는 경우에도 Pipeline을 사용할 수 있습니다.class YourPipeline: @classmethod def from_crawler(cls, crawler): pipeline = cls() crawler.signals.connect(pipeline.spider_closed, signals.spider_closed) return pipeline def spider_closed(self, spider): if hasattr(spider, 'driver'): spider.driver.quit()