参考:https://www.cnblogs.com/my8100/p/cookie_login.html
用于管理HTTP cookie值、存储HTTP请求生成的cookie。
1、注:cookielib在Python3中已经改成了http.cookiejar
try:
import cookielib
except:
import http.cookiejar as cookielib # 兼容python3方式
2、三个子类:
2.1 FileCookieJar(filename,delayload=None,policy=None)
创建FileCookieJar实例,检索cookie信息并将信息存储到文件中,filename是文件名。
2.2 MozillaCookieJar(filename,delayload=None,policy=None)
创建与Mozilla cookies.txt文件格式兼容的FileCookieJar实例,delayload为True时支持延迟访问访问文件,即只有在需要时才读取文件或在文件中存储数据。。
2.3 LWPCookieJar(filename,delayload=None,policy=None)
创建与libwww-perl Set-Cookie3文件格式兼容的FileCookieJar实例。
3、CookieJar()整个cookie都存储在内存中,对CookieJar实例进行垃圾回收后cookie也将丢失,需要和本地文件交互,就用 MozillaCookjar() 或 LWPCookieJar()。
4、cookie实例
# cookie:爬虫维持登陆状态的机制
import http.cookiejar,urllib.request
cookie = http.cookiejar.CookieJar() # 声明cookiejar的对象,存放cookie的容器
#https_handle = request.HTTPSHandler() # 创建https管理器
handler = urllib.request.HTTPCookieProcessor(cookie) # 构建handler,即cookie处理器对象
opener = urllib.request.build_opener(handler) # 构建出OPener
# 请求页面,访问之后会自动保存cookie到cookiejar中
response = opener.open('http://www.zhihu.com')
print(response.read().decode())
# 标准格式将保存的Cookie打印出来
for item in cookie:
print(item.name + '=' + item.value)
# cookie = cookiejar.MozillaCookieJar(filename)
# cookie.save(ignore_discard=True, ignore_expires=True) # 保存cookie到文件
# ignore_discard: save even cookies set to be discarded.
# ignore_expires: save even cookies that have expiredThe file is overwritten if it already exists
# cookie.load("httpbin-cookie.txt") # 从文件中读取cookie内容到变量
参考:http://www.python-requests.org/en/latest/api/#api-cookies
1、requests基础
import requests
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
}
response = requests.get('http://www.zhihu.com',headers=headers)
print(response.text)
print(response.cookies) # 对象
print(response.cookies.get_dict())
# 默认情况下,除了 HEAD, Requests 会自动处理所有重定向,可以使用响应对象的 history 方法来追踪重定向。
# Response.history 是一个 Response 对象的列表,为了完成请求而创建了这些对象。这个对象列表按照从最老到最近的请求进行排序。
print(response.history)
# if response.history:
# for r in response.history:
# self.cookies.update(r.cookies)
2、session它可以自动识别response中的set cookie,对象会在同一个Session实例发出的所有请求之间保持cookies。
# 使用登录cookie信息
session = requests.session()
session.cookies = cookielib.LWPCookieJar(filename='cookies.txt')
try:
session.cookies.load(ignore_discard=True)
except:
print("Cookie 加载失败")
。。。
session.cookies.save()
3、dict与cookiejar的转换
3.1、requests.utils.cookiejar_from_dict
requests.utils.add_dict_to_cookiejar(cj, cookie_dict)
Returns a CookieJar from a key/value dictionary.
参数:
cj -- CookieJar to insert cookies into.
cookie_dict -- Dict of key/values to insert into CookieJar.
返回类型:
CookieJar
3.2、requests.utils.dict_from_cookiejar
requests.utils.cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True)[源代码]
Returns a CookieJar from a key/value dictionary.
参数:
cookie_dict -- Dict of key/values to insert into CookieJar.
cookiejar -- (optional) A cookiejar to add the cookies to.
overwrite -- (optional) If False, will not replace cookies already in the jar with new ones.
# 小例子
# requests.utils.add_dict_to_cookiejar对session对象设置cookie
import requests
session = requests.session()
session.cookies.set('mycookie', 'value') # 设置会话cookies
# cookie_dict = {'mycookie', 'value'}
# s.cookies.update(cookie_dict)
session.get('https://www.baidu.com')
print(session.cookies.get_dict()) # 输出cookies
session.cookies.clear() # 删除cookies,也可以使用s.cookies=None的方式将所有cookies删除
c = requests.cookies.RequestsCookieJar() # 定义一个cookie对象
c.set('cookie-name', 'cookie-value') # 增加cookie的值
session.cookies.update(c) # 更新s的cookie
print(session.cookies.get_dict()) # 输出cookies
# 将CookieJar转为字典:
cookie_dict = requests.utils.dict_from_cookiejar(session.cookies)
print(cookie_dict)
# 将字典转为CookieJar:其中cookie_dict是要转换字典
cookies = requests.utils.cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True)
print(cookies)
# 转换完之后就可以把它赋给cookies 并传入到session中了
session.cookies = cookies
class zhihu:
def __init__(self):
self.session = requests.Session()
def load_cookies(self):
with open(cookies_file) as f:
# 将字典转换成RequestsCookieJar,赋值给session的cookies.
self.session.cookies = requests.utils.cookiejar_from_dict(pickle.load(f))
def save_cookies(self):
with open(cookies_file, 'w') as f:
# 将cookiejar转换成字典
pickle.dump(requests.utils.dict_from_cookiejar(self.session.cookies), f)
4、补充:
# 传递URL参数
>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.get("http://httpbin.org/get", params=payload)
class scrapy.contrib.downloadermiddleware.cookies.CookiesMiddleware
Scrapy通过CookiesMiddleware会自动管理cookies,所有的requests和response都要经过它的处理。
1、配置项:
COOKIES_ENABLED 默认: True 是否启用CookiesMiddleware
COOKIES_DEBUG 默认: False 如果启用,Scrapy将记录所有在request(Cookie 请求头)发送的cookies及response接收到的cookies(Set-Cookie 接收头)。
2、单spider单cookie session:
可以在第一次发起请求(start_request)时将cookie手动添加到scrapy.Request的cookies参数中,cookie在后续的请求中会自行流转。
scrapy.Request(url, callback=self.xxx, cookies=cookies)
3、单spider多cookie session:
例如我们注册了两个账号 account1 和 account2,一个爬虫想同时登录两个账号对网站进行爬取,为了避免 Cookie 冲突(通俗地讲,登录一个会替换掉另一个),此时可以让每个账号发送的 HTTP 请求使用不同的 CookieJar,在构造 Request 对象时,可以通过 meta 参数的cookieJar 字段指定所要使用的 CookieJar,这样就维持了多个会话。
Scrapy通过使用 cookiejar Request meta key来支持单spider追踪多cookie session,默认情况下其使用一个cookie jar(session),可以传递一个标示符来使用多个,键‘cookiejar’是一个特殊的键,scrapy在meta中见到此键后会自动将cookie传递到要callback的函数中。
for i, url in enumerate(urls):
yield scrapy.Request("http://www.example.com", meta={'cookiejar': i},
callback=self.parse_page)
cookiejar meta key不是”黏性的(sticky)”需要在之后的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)
从response header中的’Set-Cookies’中提取cookie,可以使用cookiejar.extract_cookies(response, response.request),但只会提取当前响应设置的cookie。
参考:http://www.cnblogs.com/thunderLL/p/8060279.html
CookiesMiddleware用于实现单Spider多cookie,通过在Request meta中添加cookiejar来支持单spider追踪多cookie session.默认情况下其使用一个cookie jar(session),不过您可以传递一个标示符来使用多个。
例如:
for i, url in enumerate(urls):
yield scrapy.Request("http://www.example.com", meta={'cookiejar': i},callback=self.parse_page)
注意:meta中的cookiejar仅存储了cookiejar的标识,真是的cookiejar存储在CookiesMiddleware实例的jars属性中
import os
import six
import logging
from collections import defaultdict
from scrapy.exceptions import NotConfigured
from scrapy.http import Response
from scrapy.http.cookies import CookieJar
from scrapy.utils.python import to_native_str
logger = logging.getLogger(__name__)
class CookiesMiddleware(object):
"""This middleware enables working with sites that need cookies"""
# 中间件在Scrapy启动时实例化
def __init__(self, debug=False):
# jars属性是一个默认值为CookieJar对象的dict.
self.jars = defaultdict(CookieJar)
self.debug = debug
@classmethod
def from_crawler(cls, crawler):
if not crawler.settings.getbool('COOKIES_ENABLED'):
raise NotConfigured
return cls(crawler.settings.getbool('COOKIES_DEBUG'))
def process_request(self, request, spider):
if request.meta.get('dont_merge_cookies', False):
return
# 每个cookiesjar的key都存储在 meta字典中,如果在request meta中使用了cookiejar, cookiejarkey为对应的标识,否则为None
cookiejarkey = request.meta.get("cookiejar")
jar = self.jars[cookiejarkey]
# 第一次执行jars会为每个key产生一个默认值cookiejar对象.默认为{None: cookiejar}
cookies = self._get_request_cookies(jar, request)
# 把requests的cookies存储到cookiesjar中
for cookie in cookies:
jar.set_cookie_if_ok(cookie, request)
# set Cookie header
request.headers.pop('Cookie', None)
# 添加cookiesjar中的cookies到requests header
jar.add_cookie_header(request)
self._debug_cookie(request, spider)
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]
# 在请求允许的情况下(?),从response中提取cookie并入当前的cookiejar
jar.extract_cookies(response, request)
self._debug_set_cookie(response, spider)
return response
def _debug_cookie(self, request, spider):
if self.debug:
cl = [to_native_str(c, errors='replace')
for c in request.headers.getlist('Cookie')]
if cl:
cookies = "\n".join("Cookie: {}\n".format(c) for c in cl)
msg = "Sending cookies to: {}\n{}".format(request, cookies)
logger.debug(msg, extra={'spider': spider})
def _debug_set_cookie(self, response, spider):
if self.debug:
cl = [to_native_str(c, errors='replace')
for c in response.headers.getlist('Set-Cookie')]
if cl:
cookies = "\n".join("Set-Cookie: {}\n".format(c) for c in cl)
msg = "Received cookies from: {}\n{}".format(response, cookies)
logger.debug(msg, extra={'spider': spider})
def _format_cookie(self, cookie):
# build cookie string
# 对以字典或字典的列表的形式传入的cookie进行格式化
cookie_str = '%s=%s' % (cookie['name'], cookie['value'])
if cookie.get('path', None):
cookie_str += '; Path=%s' % cookie['path']
if cookie.get('domain', None):
cookie_str += '; Domain=%s' % cookie['domain']
return cookie_str
def _get_request_cookies(self, jar, request):
# 将request中cookies参数添加的cookie合并到当前的cookiejar中
if isinstance(request.cookies, dict):
cookie_list = [{'name': k, 'value': v} for k, v in \
six.iteritems(request.cookies)]
else:
cookie_list = request.cookies
cookies = [self._format_cookie(x) for x in cookie_list]
headers = {'Set-Cookie': cookies}
# 使用刚才获取的cookie构造一个响应对象
response = Response(request.url, headers=headers)
# cookiejar.make_cookies方法从response中提取cookie放入当前cookiejar中.
return jar.make_cookies(response, request)
简要分析:
request:
1、使用字典初始化多个cookies jar
2、把每个requests指定的cookies jar 提取出来
3、然后根据policy把requests中的cookies添加cookies jar
4、最后把cookies jar中合适的cookies添加到requests首部
response:
1、先从cookies jar 字典中把requests对应的cookiesjar提取出来.
2、使用extract_cookies把response首部中的cookies添加到cookies jar