效果图:

废话

如何知道你写的爬虫有没有正常运行,运行了多长时间,请求了多少个网页,抓到了多少条数据呢?官方其实就提供了一个字典就包含一些抓取的相关信息:crawler.stats.get_stats(),crawler是scrapy中的一个组件。你可以在很多组件中访问他,比如包含from_crawler(cls, crawler)方法的所有组件。

既然能得到scrapy的运行状态,想要实时显示出来应该也很简单吧。同样是使用上一篇博客用到的influxdb+grafana来展示数据,我们只需要将scrapy的一些运行信息实时同步到influxdb这个数据库,就能通过grafana以图的形式来展示出数据库里的内容了。

写数据库

如何实时将字典同步到数据库呢?这里肯定要设定一个同步的时间间隔,假设是5秒。那么我们的需求就是让scrapy每5秒写一次爬虫运行状态的信息到数据库,上面提到能访问到crawler.stats.get_stats()这个的组件有很多,比如中间件、管道、爬虫。我们应该在哪个组件中同步信息?

这个我们可以先看一些内置的组件分别实现了什么功能,然后看和需求最相似的功能。很明显,功能最为合适的是extensions这个组件了,有很多人可能都没有用过这个组件,我在看很多博客都很少有提到这个组件的,因为这个组件能做的事,其他也能做,用它只是为了让分工更明确而已。所以一些额外的功能一般写入extensions,我们先看看内置的几个都实现了什么样的功能

  • 日志统计信息扩展(scrapy.extensions.logstats.LogStats):记录基本统计信息,例如抓取的页面和已抓取的项目
  • 核心统计信息扩展(scrapy.extensions.corestats.CoreStats): 如果启用了统计信息收集,请启用核心统计信息的收集
  • Telnet控制台扩展(scrapy.extensions.telnet.TelnetConsole): 提供一个telnet控制台,以进入当前正在运行的Scrapy进程内的Python解释器,这对于调试非常有用
  • 内存使用扩展(scrapy.extensions.memusage.MemoryUsage): 此扩展名在Windows中不起作用

其中日志统计信息扩展就是把crawler.stats.get_stats()这个字典信息写入到日志,这和我要实现的功能基本类似。所以代码可以参考参考。直接看我的代码:

import logging
from scrapy import signals
import datetime
from threading import Timer
from influxdb import InfluxDBClientlogger = logging.getLogger(__name__)class SpiderStatLogging:def __init__(self, crawler, dbparams, interval):self.exit_code = Falseself.interval = intervalself.crawler = crawlerself.client = InfluxDBClient(**dbparams)self.stats_keys = set()self.cur_d = {'log_info': 0, 'log_warning': 0,'requested': 0,'request_bytes': 0,'response': 0,'response_bytes': 0,'response_200': 0,'response_301': 0,'response_404': 0,'responsed': 0,'item': 0,'filtered': 0,}@classmethoddef from_crawler(cls, crawler):dbparams = crawler.settings.get('INFLUXDB_PARAMS')interval = crawler.settings.get('INTERVAL', 60)ext = cls(crawler, dbparams, interval)crawler.signals.connect(ext.engine_started, signal=signals.engine_started)crawler.signals.connect(ext.engine_stopped, signal=signals.engine_stopped)crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed)crawler.signals.connect(ext.spider_opened, signal=signals.spider_opened)return extdef spider_closed(self, spider, reason):logger.info(self.stats_keys)influxdb_d = {"measurement": "spider_closed","time": datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'),"tags": {'spider_name': spider.name},"fields": {'end_time': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'reason': reason,'spider_name':spider.name}}if not self.client.write_points([influxdb_d]):raise Exception('写入influxdb失败!')def spider_opened(self, spider):influxdb_d = {"measurement": "spider_opened","time": datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'),"tags": {'spider_name': spider.name},"fields": {'start_time': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),'spider_name':spider.name}}if not self.client.write_points([influxdb_d]):raise Exception('写入influxdb失败!')def engine_started(self):Timer(self.interval, self.handle_stat).start()def engine_stopped(self):self.exit_code = Truedef handle_stat(self):stats = self.crawler.stats.get_stats()d = {'log_info': stats.get('log_count/INFO', 0), 'dequeued': stats.get('scheduler/dequeued/redis', 0),'log_warning': stats.get('log_count/WARNING', 0),'requested': stats.get('downloader/request_count', 0),'request_bytes': stats.get('downloader/request_bytes', 0),'response': stats.get('downloader/response_count', 0),'response_bytes': stats.get('downloader/response_bytes', 0),'response_200': stats.get('downloader/response_status_count/200', 0),'response_301': stats.get('downloader/response_status_count/301', 0),'response_404': stats.get('downloader/response_status_count/404', 0),'responsed': stats.get('response_received_count', 0),'item': stats.get('item_scraped_count', 0),'depth': stats.get('request_depth_max', 0),'filtered': stats.get('bloomfilter/filtered', 0),'enqueued': stats.get('scheduler/enqueued/redis', 0),'spider_name': self.crawler.spider.name}for key in self.cur_d:d[key], self.cur_d[key] = d[key] - self.cur_d[key], d[key]influxdb_d = {"measurement": "newspider","time": datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'),"tags": {'spider_name': self.crawler.spider.name},"fields": d}if not self.client.write_points([influxdb_d]):raise Exception('写入influxdb失败!')self.stats_keys.update(stats.keys())if not self.exit_code:Timer(self.interval, self.handle_stat).start()

代码应该不难理解,从settings.py中读取两个变量’INFLUXDB_PARAMS’、‘INTERVAL’,然后在引擎开始的时候开启一个定时器,每隔INTERVAL秒执行一次handle_stat函数,handle_stat函数的功能就是把crawler.stats.get_stats()这个字典写入到influxdb数据库里。接着只需要在配置文件中启用这个扩展即可,

EXTENSIONS = {'项目名称.文件名称.SpiderStatLogging': 1,# 假设上面的代码都保存在extensions.py中,放在和settings.py同级目录,# 则可以写成:项目名称.extensions..SpiderStatLogging
}

展示数据库

granfana我就不多说了,不懂的请百度,或者看一下我的上一篇博客再百度。

图表json:https://lanzoux.com/icrr5kb(太长就直接放网盘了,复制到grafana导入即可)

scrapy自定义扩展(extensions)实现实时监控scrapy爬虫的运行状态相关推荐

  1. 一起体验 skywalking+es8.5.x 实时监控应用运行信息

    序言 企业应用系统发展越来越庞大,依赖越来越多的产品组件,集成越来越多系统, 整体应用系统的性能取决于"木桶短板",为了捕捉系统的短板问题,更好的持续优化,需要一套完备的" ...

  2. Python爬虫:Scrapy的Crawler对象及扩展Extensions和信号Signals

    先了解Scrapy中的Crawler对象体系 Crawler对象 settings crawler的配置管理器 set(name, value, priority='project') setdict ...

  3. 关于爬虫平台的架构设计实现和框架的选型(二)--scrapy的内部实现以及实时爬虫的实现

    我们接着关于爬虫平台的架构设计实现和框架的选型(一)继续来讲爬虫框架的架构实现和框架的选型. 前面介绍了scrapy的基本操作,下面介绍下scrapy爬虫的内部实现架构如下图 1.Spiders(爬虫 ...

  4. 关于爬虫平台的架构实现和框架的选型(二)--scrapy的内部实现以及实时爬虫的实现...

    我们接着关于爬虫平台的架构实现和框架的选型(一)继续来讲爬虫框架的架构实现和框架的选型. 前面介绍了scrapy的基本操作,下面介绍下scrapy爬虫的内部实现架构如下图 1.Spiders(爬虫): ...

  5. 案例 | 华为对Zabbix的3个探索:水平扩展、数据实时消费及网络体验监控

    "和大家分享华为对Zabbix的三个探索实践,为了解决集群管理.Agent迁移.高可用管理问题,设计了水平扩展方案.为了实时监控数据实时呈现,设计了数据实时消费方案,还有为了构建万物互联的智 ...

  6. python command line debug_【已解决】Mac中PyCharm中去加断点实时调试scrapy的项目

    折腾: 后,在之前已经用过PyCharm去加上断点实时调试别的python程序的前提下. 下载希望可以用PyCharm也可以加断点,实时调试scrapy的项目. 不过能想到的是,scrapy这种项目, ...

  7. 利用ngxtop实时监控nginx的访问情况

    利用ngxtop实时监控nginx的访问情况 关于对nginx web server的实时访问的实时监控问题,我很久之前就想实现的,现在虽有nginx自带的status扩展,但那是全局的,无法细分到v ...

  8. 别人家的防疫实时监控大屏是怎么做的?方法和技巧都在这里了

    复工返学高峰季是疫情防控的要紧时期,引起了全国企业和高校的高度重视.不少公司和学校将信息化手段应用到了防疫工作中,数字大屏可以用做防疫数据监控的前端平台,也能通过数据展示警醒大家不可放松警惕,在防疫数 ...

  9. 使用开源实时监控系统 HertzBeat 5分钟搞定 Mysql 数据库监控告警

    使用开源实时监控系统 HertzBeat 对 Mysql 数据库监控告警实践,5分钟搞定! Mysql 数据库介绍 MySQL是一个开源关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 O ...

最新文章

  1. Dialog 去白色边框及透明
  2. C语身教程第七章:布局与联结(5)
  3. mysql编辑工具wf_轻松构建自定义WF设计器
  4. 对联想乐Pad的十大期待
  5. 02 typedef
  6. linux ubutu书籍,Ubuntu Linux入门到精通[图书]
  7. 三同轴连接器_电子元器件 连接器相关知识
  8. 201509-2-日期计算
  9. DevExtreme移动开发框架
  10. 新手linux版本,六款适用于新手的非Ubuntu Linux发行版
  11. Flex 与外部的数据通信(HTTPService,URLLoader和URLRequest)
  12. 2022最新H5手机微商城运营源码 简约轻量版 对接最新Z支付个人免签接口 带搭建教程
  13. 红警辅助脚本_红警Ol全能辅助_红警自动切小号刷资源_加速采集打野_建筑升级……
  14. 【编程实践】为了带你搞懂RPC,我们手写了一个RPC框架
  15. 【转】ubuntu下为APT设置代理
  16. 公众号markdown排版神器(md转微信html)
  17. gps转百度地图坐标 java,GPS坐标与百度地图坐标转换
  18. 火车头采集成功了,虽然是这么的牵强。
  19. flume采集hive日志写到hdfs问题
  20. RabbitMQ学习(十五):消极确认(Negative Acknowledgements)

热门文章

  1. LK源码解析 9 总结
  2. 爬虫经典项目——HFUT GPA计算器
  3. 【jenkins】jenkins旧版本下载
  4. python发送文件_Python发送邮件(最全)
  5. pyecharts 中应用seaborns 调色板
  6. 创建一个图文并茂的调查
  7. Windows Server 2008 R2使用WDS服务实现批量安装操作系统演示
  8. 关于游戏陪玩系统源码后台管理系统前端项目的思考
  9. 免费IDM注册机下载
  10. 山东大学为什么火了_山东大学在985高校中处于什么水平?