一 Scrapy框架--cookie的获取/传递/本地保存

1. 完成模拟登陆
2. 登陆成功后提取出cookie,然后保存到本地cookie.txt文件中
3. 再次使用时从本地的cookie.txt中读取cookie,省略模拟登陆.

Cookie的传递和提取

  1. from scrapy.http.cookies import CookieJar
  2.  
  3. # 该模块继承自内置的http.cookiejar,操作类似
  4.  
  5. # 实例化一个cookiejar对象
  6. cookie_jar = CookieJar()
  7.  
  8. # 首先是cookie的提取
  9. class MySpider(scrapy.Spider):
  10. ....
  11. ....
  12. # 模拟登陆,之后调用一个检查是否登录成功的函数
  13. def login(self, response):
  14. ....
  15. return [scrapy.FormRequest(
  16. url=login_url,
  17. formdata = {'username':xxx, 'password':xxx},
  18. callback = self.check_login
  19. )]
  20.  
  21. def check_login(self, response):
  22. if 登录成功:
  23. # 到这里我们的登录状态已经写入到response header中的'Set-Cookies'中了,
  24. # 使用extract_cookies方法可以提取response中的cookie
  25. cookiejar.extract_cookies(response, response.request)
  26. # cookiejar是类字典类型的,将它写入到文件中
  27. with open('cookies.txt', 'w') as f:
  28. for cookie in cookie_jar:
  29. f.write(str(cookie) + '\n')
  30.  
  31. # 有些情况可能在发起登录之前会有一些请求,会陆续的产生一些cookie,可以在第一次请求的时候将cookiejar写入到request的meta中进行传递
  32. scrapy.Request(url, callback=self.xxx, meta={'cookiejar': cookiejar})
  33. # 之后每次需要传递这个cookiejar对象可以从response.meta中拿到
  34. scrapy.Request(url, callback=self.xxx, meta={'cookiejar': response.meta['cookiejar']})

看了不少博文中只是写将cookie添加到meta中,这样就可以在请求的过程中获取到cookie.我这样尝试过,cookiejar在多个请求-响应中流转后依然是空的,所以只能在需要的时候使用cookiejar.extract_cookies方法进行手动提取.
若哪位大神知道meta中的cookiejar自行获取cookie的方法,请评论指点,谢谢!

从本地文件中读取Cookie

  1. with open('cookies.txt', 'r') as f:
  2. cookiejar = f.read()
  3. p = re.compile(r'<Cookie (.*?) for .*?>')
  4. cookies = re.findall(p, cookiejar)
  5. cookies = (cookie.split('=', 1) for cookie in cookies)
  6. cookies = dict(cookies)

之后可以在第一次发起请求(start_request)时将cookie手动添加到scrapy.Requestcookies参数中,cookie在后续的请求中会自行流转.

  1. scrapy.Request(url, callback=self.xxx, cookies=cookies)

二 Scrapy源码注解--CookiesMiddleware

  1. class CookiesMiddleware(object):
  2. """
  3. 中间件在Scrapy启动时实例化.其中jars属性是一个默认值为CookieJar对象的dict.
  4. 该中间件追踪web server发送的cookie,保存在jars中,并在之后的request中发送回去,
  5. 类似浏览器的行为.
  6.  
  7. CookiesMiddleware还用于实现单Spider多cookie.通过在Request meta中添加cookiejar来支持单
  8. spider追踪多cookie session.默认情况下其使用一个cookie jar(session),不过您可以传递一个
  9. 标示符来使用多个。
  10. 例如:
  11. for i, url in enumerate(urls):
  12. yield scrapy.Request("http://www.example.com", meta={'cookiejar': i},callback=self.parse_page)
  13. 注意:meta中的cookiejar仅存储了cookiejar的标识,真是的cookiejar存储在CookiesMiddleware
  14. 例的jars属性中
  15. """
  16. def __init__(self, debug=False):
  17. self.jars = defaultdict(CookieJar)
  18. self.debug = debug
  19.  
  20. @classmethod
  21. def from_crawler(cls, crawler):
  22. # COOKIES_ENABLED默认值为True,是否启用CookiesMiddleware
  23. # COOKIES_DEBUG默认值为False,如果启用,Scrapy将记录所有在request(Cookie 请求头)发
  24. # 送的cookies及response接收到的cookies(Set-Cookie 接收头)。
  25. if not crawler.settings.getbool('COOKIES_ENABLED'):
  26. raise NotConfigured
  27. return cls(crawler.settings.getbool('COOKIES_DEBUG'))
  28.  
  29. def process_request(self, request, spider):
  30. if request.meta.get('dont_merge_cookies', False):
  31. return
  32. # 如果在request meta中使用了cookiejar, cookiejarkey为对应的标识.
  33. # 否则cookiejarkey为None
  34. cookiejarkey = request.meta.get("cookiejar")
  35. # 第一次执行jars会为每个key产生一个默认值cookiejar对象.默认为{None: cookiejar}
  36. jar = self.jars[cookiejarkey]
  37. # 见下面_get_request_cookies()方法
  38. cookies = self._get_request_cookies(jar, request)
  39. for cookie in cookies:
  40. jar.set_cookie_if_ok(cookie, request)
  41. # set Cookie header
  42. request.headers.pop('Cookie', None)
  43. # 将cookie加入到request的headers中
  44. jar.add_cookie_header(request)
  45. self._debug_cookie(request, spider)
  46.  
  47. def process_response(self, request, response, spider):
  48. if request.meta.get('dont_merge_cookies', False):
  49. return response
  50. # extract cookies from Set-Cookie and drop invalid/expired cookies
  51. cookiejarkey = request.meta.get("cookiejar")
  52. jar = self.jars[cookiejarkey]
  53. # 在请求允许的情况下(?),从response中提取cookie并入当前的cookiejar
  54. jar.extract_cookies(response, request)
  55. self._debug_set_cookie(response, spider)
  56.  
  57. return response
  58. ...
  59. ...
  60.  
  61. def _format_cookie(self, cookie):
  62. # 对以字典或字典的列表的形式传入的cookie进行格式化
  63. cookie_str = '%s=%s' % (cookie['name'], cookie['value'])
  64.  
  65. if cookie.get('path', None):
  66. cookie_str += '; Path=%s' % cookie['path']
  67. if cookie.get('domain', None):
  68. cookie_str += '; Domain=%s' % cookie['domain']
  69.  
  70. return cookie_str
  71.  
  72. def _get_request_cookies(self, jar, request):
  73. # 将request中cookies参数添加的cookie合并到当前的cookiejar中
  74. if isinstance(request.cookies, dict):
  75. cookie_list = [{'name': k, 'value': v} for k, v in \
  76. six.iteritems(request.cookies)]
  77. else:
  78. cookie_list = request.cookies
  79.  
  80. cookies = [self._format_cookie(x) for x in cookie_list]
  81. headers = {'Set-Cookie': cookies}
  82. # 使用刚才获取的cookie构造一个响应对象
  83. response = Response(request.url, headers=headers)
  84. # cookiejar.make_cookies方法从response中提取cookie放入当前cookiejar中.
  85. return jar.make_cookies(response, request)

CookiesMiddleware默认情况下实现了cookie在请求-响应之间的流转和填充.
又可以通过scrapy.Request(url, meta={'cookiejar': n})来实现单Spider多cookie.

 

scrapy 基础组件专题(十四):scrapy CookiesMiddleware源码的更多相关文章

  1. scrapy 基础组件专题(四):信号运用

    一.scrapy信号使用的简单实例 import scrapy from scrapy import signals from ccidcom.items import CcidcomItem cla ...

  2. java基础解析系列(十)---ArrayList和LinkedList源码及使用分析

    java基础解析系列(十)---ArrayList和LinkedList源码及使用分析 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder jav ...

  3. scrapy 基础组件专题(十二):scrapy 模拟登录

    1. scrapy有三种方法模拟登陆 1.1直接携带cookies 1.2找url地址,发送post请求存储cookie 1.3找到对应的form表单,自动解析input标签,自动解析post请求的u ...

  4. scrapy 基础组件专题(八):scrapy-redis 框架分析

    scrapy-redis简介 scrapy-redis是scrapy框架基于redis数据库的组件,用于scrapy项目的分布式开发和部署. 有如下特征:  分布式爬取 您可以启动多个spider工 ...

  5. scrapy 基础组件专题(九):scrapy-redis 源码分析

    下面我们来看看,scrapy-redis的每一个源代码文件都实现了什么功能,最后如何实现分布式的爬虫系统: connection.py 连接得配置文件 defaults.py 默认得配置文件 dupe ...

  6. scrapy 基础组件专题(七):scrapy 调度器、调度器中间件、自定义调度器

    一.调度器 配置 SCHEDULER = 'scrapy.core.scheduler.Scheduler' #表示scrapy包下core文件夹scheduler文件Scheduler类# 可以通过 ...

  7. 第十四章 Executors源码解析

    前边两章介绍了基础线程池ThreadPoolExecutor的使用方式.工作机理.参数详细介绍以及核心源码解析. 具体的介绍请参照: 第十二章 ThreadPoolExecutor使用与工作机理 第十 ...

  8. scrapy 基础组件专题(二):下载中间件

    下载器中间件是介于Scrapy的request/response处理的钩子框架,是用于全局修改Scrapy request和response的一个轻量.底层的系统. 1.激活Downloader Mi ...

  9. scrapy 基础组件专题(一):scrapy框架中各组件的工作流程

    Scrapy 使用了 Twisted 异步非阻塞网络库来处理网络通讯,整体架构大致如下(绿线是数据流向): Scrapy主要包括了以下组件: 引擎(Scrapy)用来处理整个系统的数据流处理, 触发事 ...

随机推荐

  1. 一网打尽枚举操作 .net core

    本文介绍如何使用枚举以及,如何将枚举类型更好的应用于项目中,看完本文可以有序的将项目中的枚举更容易的使用到每个角落. 1,分析枚举 /// <summary> /// 性别 /// < ...

  2. CISCN 2019-ikun

    0x01 进去网址,页面如下: 刚开始有个登陆和注册的按钮,上图是我已经注册后登陆成功后的页面,我们发现在图的左下角给了一个关键的提示,购买LV6,通过寻找我们发现页面数很多,大概500页,一个一个找 ...

  3. TensorFlow从0到1之TensorFlow多层感知机实现MINIST分类(22)

    TensorFlow 支持自动求导,可以使用 TensorFlow 优化器来计算和使用梯度.它使用梯度自动更新用变量定义的张量.本节将使用 TensorFlow 优化器来训练网络. 前面章节中,我们定 ...

  4. ZWave 中的消息队列机制

    文章主题   在我们的日常编程中,对消息队列的需求非常常见,使用一个简洁.高效的消息队列编程模型,对于代码逻辑的清晰性,对于事件处理的高效率来说,是非常重要的.这篇文章就来看看 ZWave 中是通过什 ...

  5. 049.Kubernetes集群管理-集群监控Metrics

    一 集群监控 1.1 Metrics Kubernetes的早期版本依靠Heapster来实现完整的性能数据采集和监控功能,Kubernetes从1.8版本开始,性能数据开始以Metrics API的 ...

  6. 【JMeter_09】JMeter逻辑控制器__临界部分控制器<Critical Section Controller>

    临界部分控制器<Critical Section Controller> 业务逻辑: 根据锁名来控制并发,同一个锁名之下,在同一时间点只能存在一个运行中,适用于控制并发的场景 锁名类型: ...

  7. ca13a_c++_顺序容器的操作6删除元素

    /*ca13a_c++_顺序容器的操作6删除元素c.erase(p) //删除迭代器p指向的位置c.erase(b,e) //删除b to e之间的数据,迭代器b包括,e不包括c.clear()//删 ...

  8. Python-17-作用域

    python有一个名为vars的内置函数,它返回变量关联的不可见的字典: >>> x = 1  >>> scope = vars()  >>> s ...

  9. c++教程网经典的c语音学习视频教程

  10. JavaScript基础JavaScript的常用编码惯例(007)

    采用一定的编码惯例,可以使得项目中的代码提到较高的一致性,可读性和可预测性. 1.缩进缩 进可以提高代码的可读性.不过错误的缩进也可能导致代码的误读.有人认为缩进应该使用tab,另外的一些人主张采用4 ...