web-dev-qa-db-fra.com

Utilisation de Scrapy avec une session utilisateur authentifiée (connectée)

Dans les Scrapy docs , il y a l'exemple suivant pour illustrer comment utiliser une session authentifiée dans Scrapy:

class LoginSpider(BaseSpider):
    name = 'example.com'
    start_urls = ['http://www.example.com/users/login.php']

    def parse(self, response):
        return [FormRequest.from_response(response,
                    formdata={'username': 'john', 'password': 'secret'},
                    callback=self.after_login)]

    def after_login(self, response):
        # check login succeed before going on
        if "authentication failed" in response.body:
            self.log("Login failed", level=log.ERROR)
            return

        # continue scraping with authenticated session...

J'ai ça qui marche, et ça va. Mais ma question est : Que devez-vous faire pour continue scraping with authenticated session, comme on dit dans le commentaire de la dernière ligne?

55
Herman Schaaf

Dans le code ci-dessus, le FormRequest utilisé pour l'authentification a le after_login fonction définie comme son rappel. Cela signifie que le after_login la fonction sera appelée et transmettra la page que la tentative de connexion a reçue comme réponse.

Il vérifie ensuite que vous êtes correctement connecté en recherchant sur la page une chaîne spécifique, dans ce cas "authentication failed". S'il le trouve, l'araignée se termine.

Maintenant, une fois que l'araignée est arrivée à ce point, elle sait qu'elle s'est authentifiée avec succès, et vous pouvez commencer à générer de nouvelles demandes et/ou gratter des données. Donc, dans ce cas:

from scrapy.selector import HtmlXPathSelector
from scrapy.http import Request

# ...

def after_login(self, response):
    # check login succeed before going on
    if "authentication failed" in response.body:
        self.log("Login failed", level=log.ERROR)
        return
    # We've successfully authenticated, let's have some fun!
    else:
        return Request(url="http://www.example.com/tastypage/",
               callback=self.parse_tastypage)

def parse_tastypage(self, response):
    hxs = HtmlXPathSelector(response)
    yum = hxs.select('//img')

    # etc.

Si vous regardez ( ici , il y a un exemple d'une araignée qui s'authentifie avant de gratter.

Dans ce cas, il gère les choses dans la fonction parse (le rappel par défaut de toute requête).

def parse(self, response):
    hxs = HtmlXPathSelector(response)
    if hxs.select("//form[@id='UsernameLoginForm_LoginForm']"):
        return self.login(response)
    else:
        return self.get_section_links(response)

Ainsi, chaque fois qu'une demande est faite, la réponse est vérifiée pour la présence du formulaire de connexion. S'il est là, alors nous savons que nous devons nous connecter, donc nous appelons la fonction appropriée, si elle n'est pas présente, nous appelons la fonction qui est responsable de gratter les données de la réponse.

J'espère que c'est clair, n'hésitez pas à demander si vous avez d'autres questions!


Modifier:

D'accord, vous voulez donc faire plus que simplement générer une seule demande et la gratter. Vous souhaitez suivre les liens.

Pour ce faire, il vous suffit de supprimer les liens pertinents de la page et de générer des demandes à l'aide de ces URL. Par exemple:

def parse_page(self, response):
    """ Scrape useful stuff from page, and spawn new requests

    """
    hxs = HtmlXPathSelector(response)
    images = hxs.select('//img')
    # .. do something with them
    links = hxs.select('//a/@href')

    # Yield a new request for each link we found
    for link in links:
        yield Request(url=link, callback=self.parse_page)

Comme vous pouvez le voir, il génère une nouvelle demande pour chaque URL de la page, et chacune de ces demandes appellera cette même fonction avec leur réponse, nous avons donc un grattage récursif en cours.

Ce que j'ai écrit ci-dessus n'est qu'un exemple. Si vous voulez "explorer" les pages, vous devriez regarder CrawlSpider plutôt que de faire les choses manuellement.

66
Acorn