Scrapy con selenium para una página web que requiere autenticación

Estoy tratando de raspar los datos de una página que tiene muchas llamadas AJAX y ejecución de javascript para hacer la página web. Así que estoy tratando de usar scrapy con selenium para hacer esto. El modus operandi es el siguiente:

  1. Agregue la URL de la página de inicio de sesión a la lista de inicio de scrapy

  2. Utilice el método de solicitud de respuesta para enviar el nombre de usuario y la contraseña para autenticarse.

  3. Una vez iniciada la sesión, solicite que se raspe la página deseada
  4. Pase esta respuesta al Selenium Webdriver para hacer clic en los botones de la página.
  5. Una vez que se hace clic en los botones y se representa una nueva página web, capture el resultado.

El código que tengo hasta ahora es el siguiente:

from scrapy.spider import BaseSpider from scrapy.http import FormRequest, Request from selenium import webdriver import time class LoginSpider(BaseSpider): name = "sel_spid" start_urls = ["http://www.example.com/login.aspx"] def __init__(self): self.driver = webdriver.Firefox() def parse(self, response): return FormRequest.from_response(response, formdata={'User': 'username', 'Pass': 'password'}, callback=self.check_login_response) def check_login_response(self, response): if "Log Out" in response.body: self.log("Successfully logged in") scrape_url = "http://www.example.com/authen_handler.aspx?SearchString=DWT+%3E%3d+500" yield Request(url=scrape_url, callback=self.parse_page) else: self.log("Bad credentials") def parse_page(self, response): self.driver.get(response.url) next = self.driver.find_element_by_class_name('dxWeb_pNext') next.click() time.sleep(2) # capture the html and store in a file 

Los 2 obstáculos que he golpeado hasta ahora son:

  1. El paso 4 no funciona. Cada vez que selenium abre la ventana de Firefox, siempre está en la pantalla de inicio de sesión y no sabe cómo superarlo.

  2. No sé cómo lograr el paso 5

cualquier ayuda será apreciada

No creo que puedas cambiar entre Peticiones desagradables y selenium de esa manera. Debe iniciar sesión en el sitio utilizando selenium, no ceder la Solicitud (). La sesión de inicio de sesión que creó con scrapy no se transfiere a la sesión de selenium. Aquí hay un ejemplo (el elemento ids / xpath será diferente para usted):

  scrape_url = "http://www.example.com/authen_handler.aspx" driver.get(scrape_url) time.sleep(2) username = self.driver.find_element_by_id("User") password = self.driver.find_element_by_name("Pass") username.send_keys("your_username") password.send_keys("your_password") self.driver.find_element_by_xpath("//input[@name='commit']").click() 

entonces puedes hacer

  time.sleep(2) next = self.driver.find_element_by_class_name('dxWeb_pNext').click() time.sleep(2) 

etc.

EDITAR: Si necesita procesar javascript y está preocupado por la velocidad / no locking, puede usar http://splash.readthedocs.org/en/latest/index.html, que debería funcionar.

http://splash.readthedocs.org/en/latest/scripting-ref.html#splash-add-cookie tiene detalles sobre cómo pasar una cookie, debería poder pasarla desde scrapy, pero no lo he hecho antes.

iniciar sesión con api scrapy primero

 # call scrapy post request with after_login as callback return FormRequest.from_response( response, # formxpath=formxpath, formdata=formdata, callback=self.browse_files ) 

pasar la sesión al controlador de cromo selenium

 # logged in previously with scrapy api def browse_files(self, response): print "browse files for: %s" % (response.url) # response.headers cookie_list2 = response.headers.getlist('Set-Cookie') print cookie_list2 self.driver.get(response.url) self.driver.delete_all_cookies() # extract all the cookies for cookie2 in cookie_list2: cookies = map(lambda e: e.strip(), cookie2.split(";")) for cookie in cookies: splitted = cookie.split("=") if len(splitted) == 2: name = splitted[0] value = splitted[1] #for my particular usecase I needed only these values if name == 'csrftoken' or name == 'sessionid': cookie_map = {"name": name, "value": value} else: continue elif len(splitted) == 1: cookie_map = {"name": splitted[0], "value": ''} else: continue print "adding cookie" print cookie_map self.driver.add_cookie(cookie_map) self.driver.get(response.url) # check if we have successfully logged in files = self.wait_for_elements_to_be_present(By.XPATH, "//*[@id='files']", response) print files