Scrapy中的内存泄漏

罗宾

我编写了以下代码来抓取电子邮件地址(用于测试):

import scrapy
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors import LinkExtractor
from scrapy.selector import Selector
from crawler.items import EmailItem

class LinkExtractorSpider(CrawlSpider):
    name = 'emailextractor'
    start_urls = ['http://news.google.com']

    rules = ( Rule (LinkExtractor(), callback='process_item', follow=True),)

    def process_item(self, response):
        refer = response.url
        items = list()
        for email in Selector(response).re("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}"):

            emailitem = EmailItem()
            emailitem['email'] = email
            emailitem['refer'] = refer
            items.append(emailitem)
        return items

不幸的是,似乎没有正确关闭对请求的引用,因为使用scrapy telnet控制台,请求的数量增加了5k / s。大约3分钟并刮掉1万页后,我的系统开始交换(8GB RAM)。任何人都知道这是怎么回事?我已经尝试删除引用并使用“复制”字符串

emailitem['email'] = ''.join(email)

没有成功。抓取后,将这些项目保存到BerkeleyDB中,以计数它们的出现(使用管道),因此之后应该删除引用。

返回一组项目和分别产生每个项目之间有什么区别?

编辑:

经过一段时间的调试后,我发现请求没有被释放,最终导致:

$> nc localhost 6023
>>> prefs()
Live References
Request 10344   oldest: 536s ago
>>> from scrapy.utils.trackref import get_oldest
>>> r = get_oldest('Request')
>>> r.url
<GET http://news.google.com>

实际上是起始网址。有人知道问题出在哪里吗?缺少对Request对象的引用在哪里?

编辑2:

在服务器(具有64GB RAM)上运行约12个小时后,使用的RAM约为16GB(使用ps,即使ps不是正确的工具)。问题是,自几个小时以来,已抓取的页面数明显减少,并且已抓取的项目数保持为0:

INFO: Crawled 122902 pages (at 82 pages/min), scraped 3354 items (at 0 items/min)

EDIT3:我做了objgraph分析,结果如下图所示(感谢@Artur Gaspar): Python Objgraph反向链接

看来我没有影响力吗?

罗宾

对我来说,最终的答案是将基于磁盘的队列与工作目录一起用作运行时参数。

这会将以下代码添加到settings.py中:

DEPTH_PRIORITY = 1 
SCHEDULER_DISK_QUEUE = 'scrapy.squeue.PickleFifoDiskQueue'
SCHEDULER_MEMORY_QUEUE = 'scrapy.squeue.FifoMemoryQueue'

之后,使用以下命令行启动搜寻器,使更改在给定目录中持久存在:

scrapy抓取{spidername} -s JOBDIR = crawls / {spidername}有关详细信息,请参见scrapy文档

这种方法的其他好处是,可以随时暂停和恢复爬网。我的蜘蛛现在运行超过11天,阻塞了约15GB内存(用于磁盘FIFO队列的文件缓存内存)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章