web-dev-qa-db-fra.com

Scrapy - comment gérer les cookies/sessions

Je suis un peu confus quant à la façon dont les cookies fonctionnent avec Scrapy et à la façon dont vous gérez ces cookies.

Ceci est fondamentalement une version simplifiée de ce que j'essaie de faire: enter image description here


Le fonctionnement du site:

Lorsque vous visitez le site Web, vous recevez un cookie de session.

Lorsque vous effectuez une recherche, le site Web se souvient de ce que vous avez recherché. Ainsi, lorsque vous faites quelque chose comme aller à la page suivante de résultats, il connaît la recherche à laquelle il se rapporte.


Mon script:

Mon araignée a une URL de début de searchpage_url

La page de recherche est demandée par parse() et la réponse du formulaire de recherche est transmise à search_generator().

search_generator() then yieldses nombreuses requêtes de recherche utilisant FormRequest et la réponse au formulaire de recherche.

Chacune de ces FormRequests, ainsi que les demandes enfants ultérieures, doit avoir sa propre session. Elle doit donc posséder son propre cookiejar et son propre cookie de session.


J'ai vu la section de la documentation qui parle d'une méta-option qui empêche la fusion des cookies. Qu'est-ce que cela signifie réellement? Cela signifie-t-il que l'araignée qui fait la demande aura son propre cookiejar pour le reste de sa vie?

Si les cookies sont alors au niveau de chaque araignée, comment cela fonctionne-t-il lorsque plusieurs araignées sont créées? Est-il possible de faire en sorte que le premier générateur de requêtes génère de nouvelles araignées et de veiller à ce que, à partir de ce moment, seule cette araignée traite les demandes futures?

Je suppose que je dois désactiver plusieurs demandes simultanées. Dans le cas contraire, un seul araignée effectuerait plusieurs recherches sous le même cookie de session et les demandes futures ne concerneraient que la recherche la plus récente.

Je suis confus, toute clarification serait grandement reçue!


MODIFIER:

Une autre option à laquelle je viens de penser est de gérer le cookie de session complètement manuellement et de le passer d’une requête à l’autre.

J'imagine que cela impliquerait de désactiver les cookies… puis de récupérer le cookie de session dans la réponse de recherche et de le transmettre à chaque requête ultérieure.

Est-ce ce que vous devriez faire dans cette situation?

45
Acorn

Trois ans plus tard, je pense que c'est exactement ce que vous recherchiez: http://doc.scrapy.org/en/latest/topics/downloader-middleware.html#std:reqmeta-cookiejar

Utilisez simplement quelque chose comme ceci dans la méthode start_requests de votre araignée:

for i, url in enumerate(urls):
    yield scrapy.Request("http://www.example.com", meta={'cookiejar': i},
        callback=self.parse_page)

Et rappelez-vous que pour les requêtes suivantes, vous devez explicitement rattacher le cookiejar:

def parse_page(self, response):
    # do some processing
    return scrapy.Request("http://www.example.com/otherpage",
        meta={'cookiejar': response.meta['cookiejar']},
        callback=self.parse_other_page)
35
Noah_S
from scrapy.http.cookies import CookieJar
...

class Spider(BaseSpider):
    def parse(self, response):
        '''Parse category page, extract subcategories links.'''

        hxs = HtmlXPathSelector(response)
        subcategories = hxs.select(".../@href")
        for subcategorySearchLink in subcategories:
            subcategorySearchLink = urlparse.urljoin(response.url, subcategorySearchLink)
            self.log('Found subcategory link: ' + subcategorySearchLink), log.DEBUG)
            yield Request(subcategorySearchLink, callback = self.extractItemLinks,
                          meta = {'dont_merge_cookies': True})
            '''Use dont_merge_cookies to force site generate new PHPSESSID cookie.
            This is needed because the site uses sessions to remember the search parameters.'''

    def extractItemLinks(self, response):
        '''Extract item links from subcategory page and go to next page.'''
        hxs = HtmlXPathSelector(response)
        for itemLink in hxs.select(".../a/@href"):
            itemLink = urlparse.urljoin(response.url, itemLink)
            print 'Requesting item page %s' % itemLink
            yield Request(...)

        nextPageLink = self.getFirst(".../@href", hxs)
        if nextPageLink:
            nextPageLink = urlparse.urljoin(response.url, nextPageLink)
            self.log('\nGoing to next search page: ' + nextPageLink + '\n', log.DEBUG)
            cookieJar = response.meta.setdefault('cookie_jar', CookieJar())
            cookieJar.extract_cookies(response, response.request)
            request = Request(nextPageLink, callback = self.extractItemLinks,
                          meta = {'dont_merge_cookies': True, 'cookie_jar': cookieJar})
            cookieJar.add_cookie_header(request) # apply Set-Cookie ourselves
            yield request
        else:
            self.log('Whole subcategory scraped.', log.DEBUG)
5
warvariuc

Je pense que l'approche la plus simple serait d'exécuter plusieurs instances du même spider en utilisant la requête de recherche comme argument d'araignée (qui serait reçu dans le constructeur), afin de réutiliser la fonctionnalité de gestion des cookies de Scrapy. Vous disposerez donc de plusieurs instances d'araignées, chacune explorant une requête de recherche spécifique et ses résultats. Mais vous devez exécuter vous-même les araignées avec: 

scrapy crawl myspider -a search_query=something

Ou vous pouvez utiliser Scrapyd pour exécuter tous les spiders via l'API JSON.

1
Pablo Hoffman
def parse(self, response):
    # do something
    yield scrapy.Request(
        url= "http://new-page-to-parse.com/page/4/",
        cookies= {
            'h0':'blah',
            'taeyeon':'pretty'
        },
        callback= self.parse
    )
0
MKatleast3