¿Cómo se hacen los scripts de selenium más rápido?

Uso python Selenium y Scrapy para rastrear un sitio web.

pero mi guión es muy lento,

Crawled 1 pages (at 1 pages/min) 

Uso CSS SELECTOR en lugar de XPATH para optimizar el tiempo. cambio los medios

 'tutorial.middlewares.MyCustomDownloaderMiddleware': 543, 

¿Es selenium demasiado lento o debería cambiar algo en Configuración?

mi código:

 def start_requests(self): yield Request(self.start_urls, callback=self.parse) def parse(self, response): display = Display(visible=0, size=(800, 600)) display.start() driver = webdriver.Firefox() driver.get("http://www.example.com") inputElement = driver.find_element_by_name("OneLineCustomerAddress") inputElement.send_keys("75018") inputElement.submit() catNums = driver.find_elements_by_css_selector("html body div#page div#main.content div#sContener div#menuV div#mvNav nav div.mvNav.bcU div.mvNavLk form.jsExpSCCategories ul.mvSrcLk li") #INIT driver.find_element_by_css_selector(".mvSrcLk>li:nth-child(1)>label.mvNavSel.mvNavLvl1").click() for catNumber in xrange(1,len(catNums)+1): print "\n IN catnumber \n" driver.find_element_by_css_selector("ul#catMenu.mvSrcLk> li:nth-child(%s)> label.mvNavLvl1" % catNumber).click() time.sleep(5) self.parse_articles(driver) pages = driver.find_elements_by_xpath('//*[@class="pg"]/ul/li[last()]/a') if(pages): page = driver.find_element_by_xpath('//*[@class="pg"]/ul/li[last()]/a') checkText = (page.text).strip() if(len(checkText) > 0): pageNums = int(page.text) pageNums = pageNums - 1 for pageNumbers in range (pageNums): WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "waitingOverlay"))) driver.find_element_by_css_selector('.jsNxtPage.pgNext').click() self.parse_articles(driver) time.sleep(5) def parse_articles(self,driver) : test = driver.find_elements_by_css_selector('html body div#page div#main.content div#sContener div#sContent div#lpContent.jsTab ul#lpBloc li div.prdtBloc p.prdtBDesc strong.prdtBCat') def between(self, value, a, b): pos_a = value.find(a) if pos_a == -1: return "" pos_b = value.rfind(b) if pos_b == -1: return "" adjusted_pos_a = pos_a + len(a) if adjusted_pos_a >= pos_b: return "" return value[adjusted_pos_a:pos_b] 

Así que su código tiene algunas fallas aquí.

  1. Utiliza selenium para analizar el contenido de la página cuando los selectores de recortes son más rápidos y más eficientes.
  2. Comienzas un webdriver para cada respuesta.

¡Esto se puede resolver de manera muy eloquent usando los progtwigs de Downloader middlewares de scrapy! Desea crear un middleware de descargador personalizado que descargue solicitudes utilizando selenium en lugar de descargador descarado.

Por ejemplo yo uso esto:

 # middlewares.py class SeleniumDownloader(object): def create_driver(self): """only start the driver if middleware is ever called""" if not getattr(self, 'driver', None): self.driver = webdriver.Chrome() def process_request(self, request, spider): # this is called for every request, but we don't want to render # every request in selenium, so use meta key for those we do want. if not request.meta.get('selenium', False): return request self.create_driver() self.driver.get(request.url) return HtmlResponse(request.url, body=self.driver.page_source, encoding='utf-8') 

Activa tu middleware:

 # settings.py DOWNLOADER_MIDDLEWARES = { 'myproject.middleware.SeleniumDownloader': 13, } 

Luego, en su araña, puede especificar qué URL descargar a través del controlador de selenium agregando un meta argumento.

 # you can start with selenium def start_requests(self): for url in self.start_urls: yield scrapy.Request(url, meta={'selenium': True}) def parse(self, response): # this response is rendered by selenium! # also can use no selenium for another response if you wish url = response.xpath("//a/@href") yield scrapy.Request(url) 

Las ventajas de este enfoque es que su controlador se inicia solo una vez y se utiliza para descargar la fuente de la página, el rest se deja en manos de las herramientas desechables asíncronas adecuadas.
Las desventajas es que no puede hacer clic en los botones y no está expuesto al controlador. La mayoría de las veces puede hacer ingeniería inversa sobre lo que hacen los botones a través del inspector de red y nunca debería tener que hacer clic con el controlador.