2017-09-19 3 views
2

Je dois être en mesure de réessayer la requête si certains xpaths n'ont pas été trouvés sur la page. J'ai donc écrit ce middleware:Comment obtenir le corps de la réponse dans le middleware scrapy downloader

class ManualRetryMiddleware(RetryMiddleware): 
    def process_response(self, request, response, spider): 
     if not spider.retry_if_not_found: 
      return response 
     if not hasattr(response, 'text') and response.status != 200: 
      return super(ManualRetryMiddleware, self).process_response(request, response, spider) 
     found = False 
     for xpath in spider.retry_if_not_found: 
      if response.xpath(xpath).extract(): 
       found = True 
       break 
     if not found: 
      return self._retry(request, "Didn't find anything useful", spider) 
     return response 

et enregistré dans settings.py:

DOWNLOADER_MIDDLEWARES = { 
    'myproject.middlewares.ManualRetryMiddleware': 650, 
    'scrapy.downloadermiddlewares.retry.RetryMiddleware': None, 
} 

Quand je lance l'araignée, je reçois

AttributeError: 'Response' object has no attribute 'xpath' 

J'ai essayé de créer manuellement sélecteur et exécuter XPath dessus ... Mais la réponse n'a aucune propriété text et response.body est octets, pas str ...

Alors, comment puis-je vérifier le contenu de la page dans un middleware? Il est possible que certaines pages ne contiennent pas les détails dont j'ai besoin, alors j'aimerais pouvoir les réessayer plus tard.

Répondre

1

La raison response ne contient pas la méthode xpath est que response paramètre dans process_response méthode de middleware téléchargeur est de type scrapy.http.Response, voir le documentation. Seulement scrapy.http.TextResponse (et scrapy.http.HtmlResponse) ont la méthode xpath. Donc avant d'utiliser xpath, créez HtmlResponse objet de response. La partie correspondante de votre classe deviendra:

... 
new_response = scrapy.http.HtmlResponse(response.url, body=response.body) 
if new_response.xpath(xpath).extract(): 
    found = True 
    break 
... 
+0

Il y a un peu de charabia dans 'new_response.text' maintenant, cependant,' specificingscrapy.http.HtmlResponse (response.url, corps = response.body, encoding = "utf-8") 'n'aide pas. –

0

Prenez également en charge votre position middleware. Il doit être avant le scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware sinon, vous pourriez finir par essayer de décoder les données compressées (ce qui ne fonctionne en effet pas). Vérifiez le response.header pour savoir si la réponse est compressée - Content-Encoding: gzip.