关于python scrapy中添加cookie踩坑记录

问题发现:

前段时间项目中,为了防止被封号(提供的可用账号太少),对于能不登录就可以抓取的内容采用不带cookie的策略,只有必要的内容才带上cookie去访问。

本来想着很简单:在每个抛出来的Request的meta中带上一个标志位,通过在CookieMiddleware中查看这个标志位,决定是否是给这个Request是否装上Cookie。

实现的代码大致如下:

class CookieMiddleware(object):
  """
  每次请求都随机从账号池中选择一个账号去访问
  """

  def __init__(self):
    client = pymongo.MongoClient(MONGO_URI)
    self.account_collection = client[MONGO_DATABASE][ACCOUNT_COLLECTION]

  def process_request(self, request, spider):
    if 'target' in request.meta:
      logging.debug('进入到process_request了')
      flag = request.meta['target']
      if flag != 'no':
        all_count = self.account_collection.find({'status': 'success'}).count()
        if all_count == 0:
          raise Exception('当前账号池为空')
        random_index = random.randint(0, all_count - 1)
        random_account = self.account_collection.find({'status': 'success'})[random_index]

        request.cookies = json.loads(random_account['cookie'])
      else:
        logging.debug('对XXX的请求不做处理')
    else:
      all_count = self.account_collection.find({'status': 'success'}).count()
      if all_count == 0:
        raise Exception('当前账号池为空')
      random_index = random.randint(0, all_count - 1)
      random_account = self.account_collection.find({'status': 'success'})[random_index]

      request.cookies = json.loads(random_account['cookie'])

在settings.py中的配置如下:

DOWNLOADER_MIDDLEWARES = {
  'eyny.middlewares.CookieMiddleware': 550,
}

到这里可能有些大佬已经能够看出端倪了,和我一样认为这么写没啥问题的同志们继续往下看。

在这么编写完之后,我正常开启了项目,还适当调高了并发量,然后第二天发现账号被封了。在debug过程中看到在抓取不需要携带cookie的url的时候,依然携带了cookie,并且cookie是被放在了header中,经过我花费了两个多小时查看框架源码之后,终于发现了原因。

原因&解决方案:

在scrapy的settings目录下的default_settings.py文件中,初始声明了一些DOWNLOADER_MIDDLEWARES_BASE,这些middlewares的声明如下:

DOWNLOADER_MIDDLEWARES_BASE = {
  # Engine side
  'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware': 100,
  'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware': 300,
  'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware': 350,
  'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware': 400,
  'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': 500,
  'scrapy.downloadermiddlewares.retry.RetryMiddleware': 550,
  'scrapy.downloadermiddlewares.ajaxcrawl.AjaxCrawlMiddleware': 560,
  'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware': 580,
  'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 590,
  'scrapy.downloadermiddlewares.redirect.RedirectMiddleware': 600,
  'scrapy.downloadermiddlewares.cookies.CookiesMiddleware': 700,
  'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 750,
  'scrapy.downloadermiddlewares.stats.DownloaderStats': 850,
  'scrapy.downloadermiddlewares.httpcache.HttpCacheMiddleware': 900,
  # Downloader side
}

可以看到在DOWNLOADER_MIDDLEWARES_BASE中也声明了一个CookiesMiddleware,而且是700,也就是说比我们写的CookieMiddleware(500)要靠后执行,而且在debug过程中也看到,在执行完我们编写的CookieMiddleware之后,header中没有携带cookie,但是在执行完scrapy.downloadermiddlewares.cookies.CookiesMiddleware: 700之后,在header中看到了cookie,这说明cookie是scrapy帮我们自动加了。

我们打开scrapy.downloadermiddlewares.cookies.CookiesMiddleware的实现源码,主要关注process_request方法:

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

  def __init__(self, debug=False):
    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

    cookiejarkey = request.meta.get("cookiejar")
    jar = self.jars[cookiejarkey]
    cookies = self._get_request_cookies(jar, request)
    for cookie in cookies:
      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)

	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

在上面的代码中,最中要的是process_request方法中的内容,可以看到首先从request.meta中查看有没有dont_merge_cookies属性,如果没有或者为false,就不运行剩下的方法,卧槽,这就是我们要找的方法呀!是不是好简单…

特别注意如果要使用dont_merge_cookies=true,那么需要我们自己将cookie加入到header中,通过**request.cookies = json.loads(random_account[‘cookie'])**方式添加的cookie,scrapy也不再会帮我们合并到header 中了。

解决方案我们的解决方法就是在request的meta中加入dont_merge_cookies属性,并设置为true,在CookieMiddleware中,我们将cookie添加在header中,而不是赋值给request.cookies

问题解决了,但是这么简单是不是很不爽,所以就继续想看看是为什么scrapy可以自动给我们加上cookie,这个接下来就需要读下面的代码了。

总结

到此这篇关于关于python scrapy中添加cookie踩坑记录的文章就介绍到这了,更多相关scrapy cookie问题内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • scrapy中如何设置应用cookies的方法(3种)

    本人是python3.6 总的来说,scrapy框架中设置cookie有三种方式. 第一种:setting文件中设置cookie 当COOKIES_ENABLED是注释的时候scrapy默认没有开启cookie 当COOKIES_ENABLED没有注释设置为False的时候scrapy默认使用了settings里面的cookie 当COOKIES_ENABLED设置为True的时候scrapy就会把settings的cookie关掉,使用自定义cookie 所以当我使用settings的cook

  • scrapy框架携带cookie访问淘宝购物车功能的实现代码

    scrapy框架简介 Scrapy是用纯Python实现一个为了爬取网站数据.提取结构性数据而编写的应用框架,用途非常广泛 框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片,非常之方便 scrapy架构图 crapy Engine(引擎): 负责Spider.ItemPipeline.Downloader.Scheduler中间的通讯,信号.数据传递等. Scheduler(调度器): 它负责接受引擎发送过来的Request请求,并按照一定的方式进行整

  • 关于python scrapy中添加cookie踩坑记录

    问题发现: 前段时间项目中,为了防止被封号(提供的可用账号太少),对于能不登录就可以抓取的内容采用不带cookie的策略,只有必要的内容才带上cookie去访问. 本来想着很简单:在每个抛出来的Request的meta中带上一个标志位,通过在CookieMiddleware中查看这个标志位,决定是否是给这个Request是否装上Cookie. 实现的代码大致如下: class CookieMiddleware(object): """ 每次请求都随机从账号池中选择一个账号去访

  • Java中Objects.equals踩坑记录

    目录 前言 1. 案发现场 2. 判断相等的方法 2.1 使用==号 2.2 使用equals方法 3. 空指针异常 4. Objects.equals的作用 5. Objects.equals的坑 总结 前言 最近review别人代码的时候,发现有个同事,在某个业务场景下,使用Objects.equals方法判断两个值相等时,返回了跟预期不一致的结果,引起了我的兴趣. 原本以为判断结果会返回true的,但实际上返回了false. 记得很早之前,我使用Objects.equals方法也踩过类似的

  • python中remove函数的踩坑记录

    摘要: 在python的使用过程中,难免会遇到要移除列表中对象的要求.这时可以使用remove函数. 对于python中的remove()函数,官方文档的解释是:Remove first occurrence of value.大意也就是移除列表中等于指定值的第一个匹配的元素. 语法 list.remove() 参数 obj 参数:从列表中删除的对象的索引 返回值 删除后不会返回值 常见用法: a = [1,2,3,4],a.remove(1),然后a就是[2,3,4]:对于a = [1,1,1

  • Python 列表和字典常踩坑即解决方案

    目录 一.关于列表 1.问题描述 2.解决方案 方案一 方案二 二.关于字典 1.问题描述 2.解决方案 结论 前言: 在Python中,如果我们想要在遍历一组数据的过程中,对这组数据进行修改,通常会出现许多问题,例如对列表进行上述操作时, 会忽略部分数据:遍历字典时,不能修改数据.本文针对这些问题,提出了多种解决方案. 一.关于列表 1.问题描述 在Python中,如果你试图在遍历一组数据的过程中,对其进行修改,这通常没什么问题. 例如: l = [3, 4, 56, 7, 10, 9, 6,

  • 快速了解Python开发中的cookie及简单代码示例

    cookie :是用户保存在用户浏览器端的一对键值对,是为了解决http的无状态连接.服务端是可以把 cookie写到用户浏览器上,用户每次发请求会携带cookie. 存放位置: 每次发请求cookie是放在请求头里面的. 应用场景: ·登陆用户和密码的记住密码 ·显示每页显示的数据,以后都是按照设定的数目显示 ·投票机制 案例用户登录 创建用户登录的url url(r'^login/', views.login), 创建登录页面 代码为: <!DOCTYPE html> <html l

  • python变量赋值机制踩坑记录

    目录 1.可变类型赋值 2.不可变类型赋值 3.自定义类型变量赋值 先说结论: 变量赋值属于浅拷贝(关于深拷贝和浅拷贝的区别可以自己了解下).故如果是可变类型变量(如a是list类型,a=b)赋值,修改a会牵连到b:如果是不可变类型(如int)的赋值,则修改任意变量不会传递. 1. 可变类型赋值 可以看出,对于可变类型赋值,变量始终指向同一块地址. 2. 不可变类型赋值 对于不可变类型变量的赋值,刚开始是指向同一块地址,但修改任意变量,则修改的变量指向另外一块地址,不会影响另外一个变量. 那么问

  • Python字符串中添加、插入特定字符的方法

    分析 我们将添加.插入.删除定义为: 添加 : 在字符串的后面或者前面添加字符或者字符串 插入 : 在字符串之间插入特定字符 在Python中,字符串是不可变的.所以无法直接删除.插入字符串之间的特定字符. 所以想对字符串中字符进行操作的时候,需要将字符串转变为列表,列表是可变的,这样就可以实现对字符串中特定字符的操作. 1.添加字符实现 添加字符或字符串 如果想在字符串 土堆 后面或者前面添加 碎念 字符串. 可以使用 + 号实现字符串的连接,或者使用方法 .join() 来连接字符串. .j

  • 如何在postman中添加cookie信息步骤解析

    在测试工作中,很多的接口都依赖于登录接口,即在调用该接口前必须有登录的信息,否则调用会报错,那如何在postman中添加cookie信息呢?主要分为两个步骤,下面为大家详细介绍: 第一步:我们首先使用postman访问登录接口,在response中找到返回的cookie信息,并拷贝: 第二步:这里我们为大家介绍两种方法 方法1:在请求接口的headers中将cookie值设置为拷贝的cookie信息: 方法2:将cookie设置为全局变量,请求接口时直接调用即可. 全局变量的配置如下: 以上就是

  • Linux/Docker 中使用 System.Drawing.Common 踩坑记录分享

    前言 在项目迁移到 .net core 上面后,我们可以使用 System.Drawing.Common 组件来操作 Image,Bitmap 类型,实现生成验证码.二维码,图片操作等功能.System.Drawing.Common 组件它是依赖于 GDI+ 的,然后在 Linux 上并没有 GDI+,面向谷歌编程之后发现,Mono 团队使用 C语言 实现了GDI+ 接口,提供对非Windows系统的 GDI+ 接口访问能力,这个应该就是libgdiplus.所以想让代码在 linux 上稳定运

  • Echarts在Taro微信小程序开发中的踩坑记录

    背景 近期笔者在使用Taro进行微信小程序开发,当引入Echarts图表库时,微信检测单包超限2M的一系列优化措施的踩坑记录,期望能指导读者少走一些弯路. 为什么选择Echarts? 微信小程序目录市面上使用最多的两款图表库,如下: echarts-for-weixin--echarts微信小程序版本 wx-charts--基于微信小程序的图表库 对比两款图表库优缺点刚好相反. echarts-for-weixin:功能强大,但体积非常大 wx-charts:功能相对简单,但体积小 由于笔者对e

随机推荐