scrapy的cookie管理

scrapy的cookie管理

单个请求的cookie管理

1.设置headers

需要把settings.py的COOKIES_ENABLED设置为false

COOKIES_ENABLED = False

示例

def start_requests(self):
    headers = {
        "cookie":"填入cookie"
    }
    url = '请求url'
    yield Request(url, callback=self.parse, headers=headers)

2.传入Request的cookies参数

需要把settings.py的COOKIES_ENABLED设置为true

示例

def start_requests(self):
    url = '请求url'
    # 指定你的cookies
    cookies = {}
    yield Request(url, callback=self.parse,cookies=cookies)

多个请求的cookie管理

上面的两个方法可适用大部分情景,但如果要管理多个cookie session,每次手动添加就显得很繁杂了。这时候就用到scrapy的cookies middleware了,其使用了cookiejar来管理多个cookie。

使用

需要把settings.py的COOKIES_ENABLED设置为true

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

只需这一步,scrapy就会自动帮你管理该次请求与响应的cookie了。而且这可以和headers与cookies传参的方式并存,它会自动帮你加入其管理的cookie中。

其中键必须为'cookiejar',与cookies middleware源码有关。

该代码为每一个请求的meta中的cookiejar都赋予不同的值(实际上它并不是真正的cookiejar,只是一个内部维持请求与cookiejar的对应的key),在cookies middleware中就为每一个请求都维持管理了不同的cookie。

上面这段代码初看可能会莫名其妙,但你看了源码就会一清二楚了。

需要注意的是后续的请求并不会自动维持前面的cookie。 如果后续的请求也要维持前面的cookie,需要在之后的request请求中接着传递。例如:

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)

源码简析

本文使用源码为scrapy 2.3.0

初始化
from collections import defaultdict
from scrapy.http.cookies import CookieJar

class CookiesMiddleware:
    """This middleware enables working with sites that need cookies"""

    def __init__(self, debug=False):
        self.jars = defaultdict(CookieJar)
        self.debug = debug

开始用defaultdict创建了self.jars,它就是实际上管理每个独立的cookiejar的字典

处理请求
def process_request(self, request, spider):
    if request.meta.get('dont_merge_cookies', False):
        return

    cookiejarkey = request.meta.get("cookiejar")
    jar = self.jars[cookiejarkey]
    for cookie in self._get_request_cookies(jar, request):
        jar.set_cookie_if_ok(cookie, request)

        # set Cookie header
        request.headers.pop('Cookie', None)
        jar.add_cookie_header(request)
        self._debug_cookie(request, spider)

cookiejarkey = request.meta.get("cookiejar")就能看出为什么meta的key必须为'cookiejar'了。这也能看到,如果meta中有{'dont_merge_cookies': True}的键值对,就会跳过处理,当有单个请求不想合并cookie就可添加该键值对。

self._get_request_cookies函数就是提取headers与request中的cookies的cookies并加入该cookiejar。这也解释了为什么cookiejar可与headers与cookies传参的方式并存。

最后为request加入该cookiejar管理的cookie

处理相应
def process_response(self, request, response, spider):
    if request.meta.get('dont_merge_cookies', False):
    return response

    # extract cookies from Set-Cookie and drop invalid/expired cookies
    cookiejarkey = request.meta.get("cookiejar")
    jar = self.jars[cookiejarkey]
    jar.extract_cookies(response, request)
    self._debug_set_cookie(response, spider)

    return response

与处理请求相似。

DEBUG

在setting.py中设置COOKIES_DEBUG = True,并且LOG_LEVEL = "DEBUG",Scrapy将记录所有在request(cookie请求头)发送的cookies及response接收到的cookies(Set-Cookie 接收头)。

下边是启用COOKIES_DEBUG 的记录的样例:

2011-04-06 14:35:10-0300 [scrapy] INFO: Spider opened
2011-04-06 14:35:10-0300 [scrapy] DEBUG: Sending cookies to: <GET http://www.diningcity.com/netherlands/index.html>
        Cookie: clientlanguage_nl=en_EN
2011-04-06 14:35:14-0300 [scrapy] DEBUG: Received cookies from: <200 http://www.diningcity.com/netherlands/index.html>
        Set-Cookie: JSESSIONID=B~FA4DC0C496C8762AE4F1A620EAB34F38; Path=/
        Set-Cookie: ip_isocode=US
        Set-Cookie: clientlanguage_nl=en_EN; Expires=Thu, 07-Apr-2011 21:21:34 GMT; Path=/
2011-04-06 14:49:50-0300 [scrapy] DEBUG: Crawled (200) <GET http://www.diningcity.com/netherlands/index.html> (referer: None)

如有纰漏,欢迎斧正

参考文献

scrapy设置cookie的三种方式

Scrapy文档

上一篇:1. Java POI 读取、写入Excel(包括样式)的工具类Utils


下一篇:pom.xml文件变灰出现删除线