首先解决爬虫等待,不被关闭的问题:

1、scrapy内部的信号系统会在爬虫耗尽内部队列中的request时,就会触发spider_idle信号。

2、爬虫的信号管理器收到spider_idle信号后,将调用注册spider_idle信号的处理器进行处理。

3、当该信号的所有处理器(handler)被调用后,如果spider仍然保持空闲状态, 引擎将会关闭该spider。

scrapy-redis 中的解决方案 在信号管理器上注册一个对应在spider_idle信号下的spider_idle()方法,当spider_idle触发是,信号管理器就会调用这个爬虫中的spider_idle(), Scrapy_redis 源码如下:

def spider_idle(self):
"""Schedules a request if available, otherwise waits."""
# XXX: Handle a sentinel to close the spider.
self.schedule_next_requests() # 这里调用
schedule_next_requests() 来从redis中生成新的请求
raise DontCloseSpider # 抛出不要关闭爬虫DontCloseSpider异常,保证爬虫活着

解决思路:

  • 通过前面的了解,我们知道 爬虫关闭的关键是 spider_idle 信号。
  • spider_idle信号只有在爬虫队列为空时才会被触发, 触发间隔为5s。
  • 那么我们也可以使用同样的方式,在信号管理器上注册一个对应在spider_idle信号下的spider_idle()方法。
  • 在 spider_idle() 方法中,编写结束条件来结束爬虫,这里以 判断redis 中关键key 是否为空,为条件

在settings.py 文件的目录下,创建一个名为 extensions.py 的文件,在其中写入以下代码

# -*- coding: utf-8 -*-

# Define here the models for your scraped Extensions
import logging
import time
from scrapy import signals
from scrapy.exceptions import NotConfigured logger = logging.getLogger(__name__) class RedisSpiderSmartIdleClosedExensions(object): def __init__(self, idle_number, crawler):
self.crawler = crawler
self.idle_number = idle_number
self.idle_list = []
self.idle_count = 0 @classmethod
def from_crawler(cls, crawler):
# first check if the extension should be enabled and raise # NotConfigured otherwise if not crawler.settings.getbool('MYEXT_ENABLED'): raise NotConfigured # 配置仅仅支持RedisSpider
if not 'redis_key' in crawler.spidercls.__dict__.keys(): raise NotConfigured('Only supports RedisSpider') # get the number of items from settings idle_number = crawler.settings.getint('IDLE_NUMBER', 360) # instantiate the extension object ext = cls(idle_number, crawler) # connect the extension object to signals crawler.signals.connect(ext.spider_opened, signal=signals.spider_opened) crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed) crawler.signals.connect(ext.spider_idle, signal=signals.spider_idle) # return the extension object return ext def spider_opened(self, spider):
logger.info("opened spider %s redis spider Idle, Continuous idle limit: %d", spider.name, self.idle_number) def spider_closed(self, spider):
logger.info("closed spider %s, idle count %d , Continuous idle count %d",
spider.name, self.idle_count, len(self.idle_list)) def spider_idle(self, spider):
self.idle_count += 1
self.idle_list.append(time.time())
idle_list_len = len(self.idle_list) # 判断 redis 中是否存在关键key, 如果key 被用完,则key就会不存在
if idle_list_len > 2 and spider.server.exists(spider.redis_key):
self.idle_list = [self.idle_list[-1]] elif idle_list_len > self.idle_number:
logger.info('\n continued idle number exceed {} Times'
'\n meet the idle shutdown conditions, will close the reptile operation'
'\n idle start time: {}, close spider time: {}'.format(self.idle_number,
self.idle_list[0], self.idle_list[0]))
# 执行关闭爬虫操作
self.crawler.engine.close_spider(spider, 'closespider_pagecount')

  

在settings.py 中添加以下配置, 请将 lianjia_ershoufang 替换为你的项目目录名。

MYEXT_ENABLED=True      # 开启扩展
IDLE_NUMBER= # 配置空闲持续时间单位为 360个 ,一个时间单位为5s # 在 EXTENSIONS 配置,激活扩展
'EXTENSIONS'= {
'lianjia_ershoufang.extensions.RedisSpiderSmartIdleClosedExensions': ,
},
MYEXT_ENABLED: 是否启用扩展,启用扩展为 True, 不启用为 False
IDLE_NUMBER: 关闭爬虫的持续空闲次数,持续空闲次数超过IDLE_NUMBER,爬虫会被关闭。默认为 ,也就是30分钟,一分钟12个时间单位

Scrapy-Redis 空跑问题,redis_key链接跑完后,自动关闭爬虫的更多相关文章

  1. 解决 Scrapy-Redis 空跑问题,链接跑完后自动关闭爬虫

    Scrapy-Redis 空跑问题,redis_key链接跑完后,自动关闭爬虫 问题:scrapy-redis框架中,reids存储的xxx:requests已经爬取完毕,但程序仍然一直运行,如何自动 ...

  2. 实现Redis Cluster并实现Python链接集群

    目录 一.Redis Cluster简单介绍 二.背景 三.环境准备 3.1 主机环境 3.2 主机规划 四.部署Redis 4.1 安装Redis软件 4.2 编辑Redis配置文件 4.3 启动R ...

  3. ETL过程跑完后,使用python发送邮件

    目标库中,如果有行数为0的表,使用python发送邮件 # -*- coding:utf-8 -*- # Author: zjc # Description:send monitor info to ...

  4. appium 链接真机后,运行代码,但是APP并没有启动

    要淡定,链接真机后,问题一下多出来这么多,还没有启动程序,就碰到接二连三的问题. 爽到家了.慢慢解决吧. 具体问题是这样的: # coding=utf-8from appium import webd ...

  5. 【week6】约跑App视频链接

    约跑视频链接发布在优酷,链接如下: http://v.youku.com/v_show/id_XMTc3NTcyNTcyNA==.html 秒拍视频连接: http://www.miaopai.com ...

  6. idea本地跑代码和链接开发机设置

  7. 基于Python,scrapy,redis的分布式爬虫实现框架

    原文  http://www.xgezhang.com/python_scrapy_redis_crawler.html 爬虫技术,无论是在学术领域,还是在工程领域,都扮演者非常重要的角色.相比于其他 ...

  8. Scrapy+redis实现分布式爬虫

    概述 什么是分布式爬虫 需要搭建一个由n台电脑组成的机群,然后在每一台电脑中执行同一组程序,让其对同一网络资源进行联合且分布的数据爬取. 原生Scrapy无法实现分布式的原因 原生Scrapy中调度器 ...

  9. 关于2440的裸跑程序中SD卡读后不能成功写入问题的讨论

    问题描述: TQ2440的官方裸跑程序中,对SD卡先进行读操作,然后再写,发现不能程序卡死.倘若对SD卡先写后读,程序可以正常运行,奇哉怪哉? 写数据的关键代码--> while(i < ...

随机推荐

  1. Server runtime

    spring mvc常用的注解: 个介绍. @Controller @Controller 负责注册一个bean 到spring 上下文中,bean 的ID 默认为 类名称开头字母小写,你也可以自己指 ...

  2. Python初学者第十七天 函数(1)

    17day 函数 1.函数定义: 函数 是指将一组语句的集合通过一个名字(函数名)封装起来,想要执行这个函数,只需调用其函数名即可 2.函数的特性: a 减少重复代码 b 使程序变得可扩展 c 使程序 ...

  3. 【MyBatis】MyBatis实现CRUD操作

    1.实现基本CRUD功能 使用MyBatis对数据完整的操作,也就是CRUD功能的实现.根据之前的内容,要想实现CRUD,只需要进行映射文件的配置. 范例:修改EmpMapper.xml文件,实现CR ...

  4. 乘风破浪:LeetCode真题_020_Valid Parentheses

    乘风破浪:LeetCode真题_020_Valid Parentheses 一.前言 下面开始堆栈方面的问题了,堆栈的操作基本上有压栈,出栈,判断栈空等等,虽然很简单,但是非常有意义. 二.Valid ...

  5. Python、R对比分析

    一.Python与R功能对比分析 1.python与R相比速度要快.python可以直接处理上G的数据:R不行,R分析数据时需要先通过数据库把大数据转化为小数据(通过groupby)才能交给R做分析, ...

  6. Java.util 包(Date 类、Calendar类、Random类)

    java.util 包提供了一些实用的方法和数据结构. Date 类 Date 类表示日期和时间,里面封装了操作日期和时间的方法.Date 类经常用来获取系统当前时间. 构造方法: 构造方法 说明 D ...

  7. mac 学习笔记

    1.关于launchctl http://zhengwei.name/2011/11/lanunchctl-notes/ 2.php-fpm 默认配置 php-fpm.conf :/etc/php-f ...

  8. python 中的Array,Value及内存共享

    官网文档的例子 from multiprocessing import Process, Value, Array def f(n, a): n.value = 3.1415927 for i in ...

  9. 【[AHOI2008]逆序对】

    被锤爆了 被这个题搞得自闭了一上午,觉得自己没什么前途了 我又没有看出来这个题的一个非常重要的性质 我们填进去的数一定是单调不降的 首先如果填进去的数并不是单调不降的,那么填进去本身就会产生一些逆序对 ...

  10. mongodb3.2副本集配置

    网上的资料太乱了,等弄好了再看官网才发现官网写的最清晰和简洁 推荐官网的副本集配置:https://docs.mongodb.com/manual/tutorial/deploy-replica-se ...