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:
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 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 yield
ses 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!
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?
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)
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)
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.
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
)