Autenticación NTLM con Scrapy para raspado web

Estoy intentando eliminar datos de un sitio web que requiere autenticación.
He podido iniciar sesión correctamente utilizando solicitudes y HttpNtlmAuth con lo siguiente:

s = requests.session() url = "https://website.com/things" response = s.get(url, auth=HttpNtlmAuth('DOMAIN\\USERNAME','PASSWORD')) 

Me gustaría explorar las capacidades de Scrapy, sin embargo, no he podido autenticarme correctamente.

Encontré el siguiente middleware que parece que podría funcionar pero no creo que lo haya implementado correctamente:

https://github.com/reimund/ntlm-middleware/blob/master/ntlmauth.py

En mi settings.py tengo

 SPIDER_MIDDLEWARES = { 'test.ntlmauth.NtlmAuthMiddleware': 400, } 

y en mi clase de araña tengo

 http_user = 'DOMAIN\\USER' http_pass = 'PASS' 

No he podido hacer que esto funcione.

Si alguien ha podido arrancar con éxito un sitio web con autenticación NTLM puede orientarme en la dirección correcta, lo apreciaría.

Pude averiguar lo que estaba pasando.

1: Esto se considera un “DOWNLOADER_MIDDLEWARE” y no un “SPIDER_MIDDLEWARE”.

 DOWNLOADER_MIDDLEWARES = { 'test.ntlmauth.NTLM_Middleware': 400, } 

2: El middleware que estaba intentando usar necesitaba ser modificado significativamente. Esto es lo que funciona para mí:

 from scrapy.http import Response import requests from requests_ntlm import HttpNtlmAuth class NTLM_Middleware(object): def process_request(self, request, spider): url = request.url pwd = getattr(spider, 'http_pass', '') usr = getattr(spider, 'http_user', '') s = requests.session() response = s.get(url,auth=HttpNtlmAuth(usr,pwd)) return Response(url,response.status_code,{}, response.content) 

Dentro de la araña, todo lo que necesitas hacer es establecer estas variables:

 http_user = 'DOMAIN\\USER' http_pass = 'PASS' 

Gracias a @SpaceDog por el comentario anterior, enfrenté un problema similar al intentar rastrear un sitio web de intranet mediante la autenticación ntlm. El rastreador solo vería la primera página porque LinkExtractor dentro del CrawlSpider no se activó.

Aquí está mi solución de trabajo usando scrapy 1.0.5

NTLM_Middleware.py

 from scrapy.http import Response, HtmlResponse import requests from requests_ntlm import HttpNtlmAuth class NTLM_Middleware(object): def process_request(self, request, spider): url = request.url usr = getattr(spider, 'http_usr', '') pwd = getattr(spider, 'http_pass','') s = requests.session() response = s.get(url, auth=HttpNtlmAuth(usr,pwd)) return HtmlResponse(url,response.status_code, response.headers.iteritems(), response.content) 

settings.py

 import logging # Crawl responsibly by identifying yourself (and your website) on the user-agent USER_AGENT = 'scrapy intranet' # Configure maximum concurrent requests performed by Scrapy (default: 16) CONCURRENT_REQUESTS=16 # Enable or disable downloader middlewares # See http://scrapy.readthedocs.org/en/latest/topics/downloader-middleware.html DOWNLOADER_MIDDLEWARES = { 'intranet.NTLM_Middleware.NTLM_Middleware': 200, 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware':None } # Configure item pipelines # See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html ITEM_PIPELINES = { 'scrapyelasticsearch.scrapyelasticsearch.ElasticSearchPipeline', } ELASTICSEARCH_SERVER='localhost' ELASTICSEARCH_PORT=9200 ELASTICSEARCH_USERNAME='' ELASTICSEARCH_PASSWORD='' ELASTICSEARCH_INDEX='intranet' ELASTICSEARCH_TYPE='pages_intranet' ELASTICSEARCH_UNIQ_KEY='url' ELASTICSEARCH_LOG_LEVEL=logging.DEBUG 

arañas / intranetspider.py

 # -*- coding: utf-8 -*- import scrapy #from scrapy import log from scrapy.spiders import CrawlSpider, Rule, Spider from scrapy.linkextractors import LinkExtractor from scrapy.linkextractors.lxmlhtml import LxmlLinkExtractor from scrapy.http import Response import requests import sys from bs4 import BeautifulSoup class PageItem(scrapy.Item): body=scrapy.Field() title=scrapy.Field() url=scrapy.Field() class IntranetspiderSpider(CrawlSpider): http_usr='DOMAIN\\user' http_pass='pass' name = "intranetspider" protocol='https://' allowed_domains = ['intranet.mydomain.ca'] start_urls = ['https://intranet.mydomain.ca/'] rules = (Rule(LinkExtractor(),callback="parse_items",follow=True),) def parse_items(self, response): self.logger.info('Crawl de la page %s',response.url) item = PageItem() soup = BeautifulSoup(response.body) #remove script tags and javascript from content [x.extract() for x in soup.findAll('script')] item['body']=soup.get_text(" ", strip=True) item['url']=response.url return item