在Scrapy爬虫中访问会话cookie

19

我试图在一个爬虫中访问会话 cookie。首先,在爬虫中使用以下方式登录到社交网络:

    def parse(self, response):

        return [FormRequest.from_response(response,
                formname='login_form',
                formdata={'email': '...', 'pass':'...'},
                callback=self.after_login)]

after_login中,我希望能够访问会话cookie,以便将它们传递给另一个模块(这里是selenium),以进一步处理具有身份验证会话的页面。
我想要像这样的东西:
     def after_login(self, response):

        # process response
        .....

        # access the cookies of that session to access another URL in the
        # same domain with the autehnticated session.
        # Something like:
        session_cookies = XXX.get_session_cookies()
        data = another_function(url,cookies)

不幸的是,response.cookies没有返回会话cookie。

我该如何获取会话cookie?我查看了cookies中间件:scrapy.contrib.downloadermiddleware.cookiesscrapy.http.cookies,但好像没有简单直接的方法来访问会话cookie.

以下是有关我原始问题的更多细节:

不幸的是,我尝试了您的想法,但没有看到cookie,尽管我确信它们存在,因为scrapy.contrib.downloadermiddleware.cookies中间件确实打印了cookie!这正是我想要获取的cookie。

所以这是我正在做的事情:

after_login(self,response)方法在适当的身份验证后接收响应变量,然后我使用带有会话数据的URL:

  def after_login(self, response):

        # testing to see if I can get the session cookies
        cookieJar = response.meta.setdefault('cookie_jar', CookieJar())
        cookieJar.extract_cookies(response, response.request)
        cookies_test = cookieJar._cookies
        print "cookies - test:",cookies_test

        # URL access with authenticated session
        url = "http://site.org/?id=XXXX"     
        request = Request(url=url,callback=self.get_pict)   
        return [request] 

如下输出所示,确实存在cookie,但我无法使用cookieJar来捕获它们。
cookies - test: {}
2012-01-02 22:44:39-0800 [myspider] DEBUG: Sending cookies to: <GET http://www.facebook.com/profile.php?id=529907453>
    Cookie: xxx=3..........; yyy=34.............; zzz=.................; uuu=44..........

我希望获得一个包含键为xxx、yyy等及其相应值的字典。谢谢 :)

我理解的是,您想在Facebook上进行身份验证,但同时又想从一个不同的域名上获取数据,这个域名是通过Facebook身份验证的吗? - warvariuc
4个回答

12

一个经典的例子是拥有一个登录服务器,在成功登录后提供新的会话ID。这个新的会话ID应该与另一个请求一起使用。

这里是我找到的源代码,看起来对我很有效。

print 'cookie from login', response.headers.getlist('Set-Cookie')[0].split(";")[0].split("=")[1]

代码:

def check_logged(self, response):
tmpCookie = response.headers.getlist('Set-Cookie')[0].split(";")[0].split("=")[1]
print 'cookie from login', response.headers.getlist('Set-Cookie')[0].split(";")[0].split("=")[1]
cookieHolder=dict(SESSION_ID=tmpCookie)

#print response.body
if "my name" in response.body:
    yield Request(url="<<new url for another server>>",   
        cookies=cookieHolder,
        callback=self."<<another function here>>")
else:
    print "login failed"
        return 

7
也许这有些过度,但我不知道你将如何使用那些Cookies,所以这可能会有用(摘自实际代码 - 根据你的情况进行调整):
from scrapy.http.cookies import CookieJar

class MySpider(BaseSpider):

    def parse(self, response):

        cookieJar = response.meta.setdefault('cookie_jar', CookieJar())
        cookieJar.extract_cookies(response, response.request)
        request = Request(nextPageLink, callback = self.parse2,
                      meta = {'dont_merge_cookies': True, 'cookie_jar': cookieJar})
        cookieJar.add_cookie_header(request) # apply Set-Cookie ourselves

CookieJar有一些有用的方法。

如果你仍然看不到cookie-也许它们不存在?


更新:

查看CookiesMiddleware代码:

class CookiesMiddleware(object):
    def _debug_cookie(self, request, spider):
        if self.debug:
            cl = request.headers.getlist('Cookie')
            if cl:
                msg = "Sending cookies to: %s" % request + os.linesep
                msg += os.linesep.join("Cookie: %s" % c for c in cl)
                log.msg(msg, spider=spider, level=log.DEBUG)

所以,请尝试使用request.headers.getlist('Cookie')

2
非常感谢您的回答!不幸的是,它仍然没有起作用。但是,我确定有cookie存在。请参见下面的帖子了解我所做的事情。 - mikolune
请查看我对原帖的编辑以查看我的回复!非常感谢 :) - mikolune
@mikolune,请查看更新。同时,学会查看源代码——这就是为什么Python很好用的原因——你可以查看源代码,有时这是最好的文档。 - warvariuc
非常感谢warvariuc。对于我的特定问题,我找到了一个解决方法,不需要访问cookies(它还有其他好处)。但这似乎是解决方案。我会在几天后尝试并在此通知您结果。 - mikolune

1

这对我有效

response.request.headers.get('Cookie')

似乎会返回中间件在请求、会话或其他方面引入的所有 cookie。

0
截至2021年(Scrapy 2.5.1),这仍不是特别简单的过程。但是您可以通过self.crawler.engine.downloader从蜘蛛中访问下载器中间件(例如CookiesMiddleware):
def after_login(self, response):
    downloader_middlewares = self.crawler.engine.downloader.middleware.middlewares
    cookies_mw = next(iter(mw for mw in downloader_middlewares if isinstance(mw, CookiesMiddleware)))
    jar = cookies_mw.jars[response.meta.get('cookiejar')].jar

    cookies_list = [vars(cookie) for domain in jar._cookies.values() for path in domain.values() for cookie in path.values()]
    # or
    cookies_dict = {cookie.name: cookie.value for domain in jar._cookies.values() for path in domain.values() for cookie in path.values()}

    ...

上述两种输出格式都可以通过cookies参数传递给其他请求。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接