ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스파이더에서 크롤링을 실행할 때 스크래피에 의해 생성되는 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()
    


     

     

     

     

    출처 : https://stackoverflow.com/questions/61243622/how-to-reduce-number-of-selenium-webdriver-instances-being-spawned-by-scrapy-on

    댓글

Designed by Tistory.