Scrapy - 如何管理cookie /会话

时间:2011-02-12 23:51:02

标签: python session cookies session-cookies scrapy

我对于如何使用Scrapy以及如何管理这些cookie感到困惑。

这基本上是我正在尝试做的简化版本: enter image description here


网站的运作方式:

当您访问该网站时,您将获得一个会话cookie。

当您进行搜索时,网站会记住您搜索的内容,因此当您执行类似于下一页结果的操作时,它会知道它正在处理的搜索。


我的剧本:

我的蜘蛛有一个searchpage_url的起始网址

parse()请求搜索页面,搜索表单回复传递给search_generator()

search_generator()然后yield使用FormRequest和搜索表单回复的大量搜索请求。

每个FormRequests以及后续子请求都需要拥有自己的会话,因此需要拥有自己的cookiejar和自己的会话cookie。


我已经看过文档的一部分,讨论了阻止cookie被合并的元选项。这究竟意味着什么?是否意味着提出请求的蜘蛛将在其余生中拥有自己的cookiejar?

如果cookie是按蜘蛛级别进行的,那么当生成多个蜘蛛时它是如何工作的?是否有可能只使第一个请求生成器产生新的蜘蛛,并确保从那时起只有该蜘蛛处理未来的请求?

我假设我必须禁用多个并发请求..否则一个蜘蛛会在同一会话cookie下进行多次搜索,而未来的请求只会与最近的搜索有关?

我很困惑,任何澄清都会受到极大的欢迎!


编辑:

我刚才想到的另一个选择是完全手动管理会话cookie,并将其从一个请求传递给另一个请求。

我想这意味着禁用cookie ..然后从搜索响应中抓取会话cookie,并将其传递给每个后续请求。

这是你在这种情况下应该做的吗?

5 个答案:

答案 0 :(得分:36)

三年后,我认为这正是您所寻找的: http://doc.scrapy.org/en/latest/topics/downloader-middleware.html#std:reqmeta-cookiejar

在蜘蛛的start_requests方法中使用类似的东西:

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

请记住,对于后续请求,您需要每次都明确重新附加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)

答案 1 :(得分:5)

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)

答案 2 :(得分:1)

我认为最简单的方法是使用搜索查询作为蜘蛛参数(将在构造函数中接收)运行同一蜘蛛的多个实例,以便重用Scrapy的cookie管理功能。因此,您将拥有多个蜘蛛实例,每个实例都会抓取一个特定的搜索查询及其结果。但是你需要自己运行蜘蛛:

scrapy crawl myspider -a search_query=something

或者您可以使用Scrapyd通过JSON API运行所有蜘蛛。

答案 3 :(得分:0)

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
    )

答案 4 :(得分:0)

Scrapy 实现了一个 downloader middleware CookiesMiddleware 来支持 cookie。你只需要启用它。它模仿了浏览器中 cookiejar 的工作方式。

  • 当请求通过 CookiesMiddleware 时,它会读取此域的 cookie 并将其设置在标头 Cookie 上。
  • 当响应返回时,CookiesMiddleware 读取从服务器发送的响应头 Set-Cookie 上的 cookie。并将其保存/合并到 mw 上的 cookiejar 中。

<块引用>

我看过文档中讨论阻止合并 cookie 的元选项的部分。这实际上意味着什么?这是否意味着发出请求的蜘蛛将在其余生中拥有自己的 cookiejar?

如果 cookie 是在每个蜘蛛级别上,那么当生成多个蜘蛛时它是如何工作的?

每个蜘蛛都有自己唯一的下载中间件。所以蜘蛛有单独的饼干罐。

通常,来自一个 Spider 的所有请求共享一个 cookiejar。但是 CookiesMiddleware 可以选择自定义此行为

  • Request.meta["dont_merge_cookies"] = True 告诉 mw 这个请求没有从 cookiejar 中读取 Cookie。并且不要将来自 resp 的 Set-Cookie 合并到 cookiejar 中。这是一个请求级别的开关。
  • CookiesMiddleware 支持多个 cookiejar。您必须控制在请求级别使用哪个 cookiejar。 Request.meta["cookiejar"] = custom_cookiejar_name

请提供CookiesMiddleware的文档和相关源代码。