2016-07-09 1 views
3

Je cette règle pour scrapy CrawlSpiderrègles Scrapy ne fonctionne pas lorsque process_request et paramètre de rappel sont mis

rules = [ 
     Rule(LinkExtractor(
        allow= '/topic/\d+/organize$', 
        restrict_xpaths = '//div[@id= "zh-topic-organize-child-editor"]' 
        ), 
      process_request='request_tagPage', callback = "parse_tagPage", follow = True) 
    ] 

request_tagePage() fait référence à une fonction pour ajouter des cookies dans les demandes et parse_tagPage() fait référence à une fonction pour analyser les pages cibles. Selon documentation, CrawlSpider devrait utiliser request_tagPage pour faire des demandes et une fois que les réponses sont retournées, il appelle parse_tagPage() pour l'analyser. Cependant, j'ai réalisé que lorsque request_tagPage() est utilisé, spider n'appelle pas du tout parse_tagPage(). Ainsi, dans le code actuel, ajouter manuellement parse_tagPage() fonction de rappel comme un rappel à request_tagPage, comme ceci:

def request_tagPage(self, request): 
    return Request(request.url, meta = {"cookiejar": 1}, \ # attach cookie to the request otherwise I can't login 
      headers = self.headers,\ 
      callback=self.parse_tagPage) # manually add a callback function. 

Cela a fonctionné, mais maintenant l'araignée ne l'utilise pas de règles pour étendre son rampants. Il se ferme après avoir parcouru les liens de start_urls. Toutefois, avant de définir manuellement le parse_tagPage() comme rappel dans request_tagPage(), les règles fonctionnent. Donc je pense que c'est peut-être un bug? Est-ce un moyen d'activer request_tagPage(), dont j'ai besoin d'attacher cookie dans la demande, parse_tagPage(), qui permet d'analyser une page et rules, ce qui dirige spider pour explorer?

+1

Etes-vous sûr que votre linkextactor travaille même? ouvrir un site Web via 'scrapy shell url' et importer LinkExtractor et essayer de l'utiliser avec les mêmes arguments sur le' response.body'. – Granitosaurus

+0

Ça marche. Lorsque parse_tagPage() n'est pas utilisé comme fonction de rappel dans request_tagPage(), je vois à partir de la console que spider explore comme il se doit. De scrapy [documentation sur l'objet Rule] (http://doc.scrapy.org/en/latest/topics/spiders.html?highlight=rule#scrapy.spiders.Rule), je pensais définir parse_tagPage() comme rappel pour le La règle est suffisante, il s'est avéré que la fonction de rappel n'était pas appelée du tout. Je dois donc mettre callback dans le request_tagPage(). Alors le callbback est appelé mais spider perd la capacité de suivre les liens, sauf ceux dans le start_urls. – Skywalker326

+0

Avez-vous essayé de ne pas construire d'objet 'Request' tout neuf, mais utilisez la méthode' Request.replace() 'à la place? Par exemple. 'return request.replace (meta = {'cookiejar': 1}, en-têtes = self.headers)'. 'CrawlSpider' gère toutes les pages de son propre callback' parse() 'qui traite les règles d'analyse, donc changer' callback' semble ne pas être une bonne solution. – shirk3y

Répondre

1

J'ai trouvé le problème. CrawlSpider utilise sa valeur par défaut parse() pour appliquer les règles. Donc, quand ma coutume parse_tagPage() est appelée, il n'y a plus de suivi parse() pour continuer à appliquer les règles. La solution consiste simplement à ajouter le parse() par défaut dans mon parse_tagPage() personnalisé. Il ressemble maintenant à ceci:

def parse_tagPage(self, response): 
    # parse the response, get the information I want... 
    # save the information into a local file... 
    return self.parse(response) # simply calls the default parse() function to enable the rules 
2

Les demandes générées par CrawlSpider règles utilisent internal callbacks and use meta to do their "magic".

Je vous suggère de ne pas recréer les Requêtes à partir de zéro dans les crochets process_request de vos règles (ou vous finirez probablement par réimplémenter ce que CrawlSpider fait déjà pour vous).

Au lieu de cela, si vous voulez juste ajouter des biscuits et des en-têtes spéciaux, vous pouvez utiliser .replace() method on the request qui est passé à request_tagPage, de sorte que la « magie » de CrawlSpider est préservée.

Quelque chose comme cela devrait être suffisant:

def request_tagPage(self, request): 
    tagged = request.replace(headers=self.headers) 
    tagged.meta.update(cookiejar=1) 
    return tagged