scrapy killed原因探究

1,194 阅读3分钟

这是我参与更文挑战的第3天

scrapy killed原因探究

用scrapy爬取网站的时候,爬取到一定的时间,会被系统主动kill 掉. 在这里插入图片描述

原因

在爬取到一定的时间,再爆掉,说明不是网络或者系统问题,只有一种可能,就是爬取的时候积累内存,最后内存溢出,导致系统kill,值得一提的是,被kill时,日志是不会记录停止原因的,最后死的不明不白,但会在console中output一个killed(如果你不是后台运行的话)

使用命令查看

egrep -i 'killed process' /var/log/syslog

在这里插入图片描述

total-vm:进程总共使用的虚拟内存; anon-rss:虚拟内存实际占用的物理内存; file-rss:虚拟内存实际占用的磁盘空间; OOM killer LINUX内核Out-Of-Memory killer机制是一种防止内存耗尽影响系统运行而采用的一种自我保护机制。 根据内核源码oom_kill.c中的定义,系统会依据“进程占用的内存”,“进程运行的时间”,“进程的优先级”,“是否为 root 用户进程“,”子进程个数和占用内存“,”用户控制参数oom_adj ”等计算一个oom_score值,分数越高就越会被内核优先杀掉。

可以看到确实是内存爆了,导致被杀.

什么会导致scrapy内存溢出呢?

众所周知,scrapy作为一个异步框架,内存溢出听起来就很怪,事实上,scrapy的一些设置是会导致内存溢出的,如官方文档所示(重点关注==too many request==): 在这里插入图片描述

可能导致内存溢出的元素

在这里插入图片描述

lxml吃掉内存

由于scrapy的底层解析是建立在lxml上的,当lxml解析文档时,一些操作会导致它大量吃掉内存,官方doc在这里插入图片描述 ==写xpath的时候,如果保留对解析元素的引用,就会保留树的记忆,从而导致内存暴涨,所以不推荐那样的写法==

如何查看scrapy内存使用

使用telent

在shell里使用: 
telent localhost 6023
username: 默认是scrapy
Username: scrapy
password是爬虫运行时输出的telent password
Password: 

在这里插入图片描述

使用prefs()查看scrapy指标

在这里插入图片描述

从上图可以看到,爬虫运行2000多秒时,scrapy的scheduler已经堆积了1318个request等待处理,600多的response等待处理.

使用 muppy 查看内存 使用

__author__ = '笑笑布丁'
# 首先
pip install Pympler
# 盗文死妈
from pympler import muppy
from pympler import summary
all_objects = muppy.get_objects()
suml = summary.summarize(all_objects)
len(all_objects)  查看大小

在这里插入图片描述

summary.print_(suml)  综合分析

在这里插入图片描述

可以看到问题爬虫运行到600s秒时,bytes就已经暴涨到500多MB了,这是导致问题爬虫运行一段时间后暴毙的原因.

解决办法

措施

  1. 减少xpath对元素的引用
  2. 调整 yield request的访问次序
  3. 减少同时运行爬虫数目
  4. 检查代码中是否不正确的判断,导致陷入死循环

结果

在这里插入图片描述

相比之前,bytes已经在600多s时降到了94.55MB.

参考文档

scrapy debugging memory doc