Scrapy蜘蛛内存泄漏

Ald*_*und 13 python memory-leaks scrapy scrapyd

我的蜘蛛有一个严重的内存泄漏..运行15分钟后,它的内存5gb和scrapy告诉(使用prefs())有900k请求对象,那就是全部.这么多生活请求对象的原因是什么?请求只会上升并且不会下降.所有其他对象都接近于零.

我的蜘蛛看起来像这样:

class ExternalLinkSpider(CrawlSpider):
  name = 'external_link_spider'
  allowed_domains = ['']
  start_urls = ['']

  rules = (Rule(LxmlLinkExtractor(allow=()), callback='parse_obj', follow=True),)

  def parse_obj(self, response):
    if not isinstance(response, HtmlResponse):
        return
    for link in LxmlLinkExtractor(allow=(), deny=self.allowed_domains).extract_links(response):
        if not link.nofollow:
            yield LinkCrawlItem(domain=link.url)
Run Code Online (Sandbox Code Playgroud)

这里输出prefs()

HtmlResponse                        2   oldest: 0s ago 
ExternalLinkSpider                  1   oldest: 3285s ago
LinkCrawlItem                       2   oldest: 0s ago
Request                        1663405   oldest: 3284s ago
Run Code Online (Sandbox Code Playgroud)

在一些网站上,100k页面的内存可以达到40gb标记(例如,在victorinox.com上,在100k页面标记处达到35gb内存).在其他它更小.

UPD.

运行一段时间后最旧请求的对象

在此输入图像描述

Rej*_*ted 8

我立即看到了一些可能的问题.

在开始之前,我想提一下prefs()没有显示排队的请求数,它显示了活动的Request()对象的数量.可以引用请求对象并使其保持活动状态,即使它不再排队等待下载.

我没有在你提供的代码中看到任何导致这种情况的内容,但你应该记住它.

马上,我会问:你在用饼干吗?如果不是,将会话ID作为GET变量传递的站点将为每次页面访问生成新的sessionID.你基本上会一遍又一遍地继续排队相同的页面.例如,victorinox.com将在其URL字符串中包含类似"jsessionid = 18537CBA2F198E3C1A5C9EE17B6C63AD"的内容,每个新页面加载的ID都会更改.

其次,你可能会遇到一个蜘蛛陷阱.也就是说,一个只重新加载自己的页面,带有新的无限链接.想想一个带有"下个月"和"上个月"链接的日历.不过,我在victorinox.com上没有直接看到任何内容.

第三,从提供的代码中,您的Spider不受任何特定域的限制.它将提取它在每个页面parse_obj上找到的每个链接,并在每个页面上运行.例如,victorinox.com的主页有一个指向http://www.youtube.com/victorinoxswissarmy的链接.这将通过大量的YouTube链接填充您的请求.

但是,您需要对更多问题进行故障排除,以确切了解发生了什么.

您可能想要使用的一些策略:

  1. 创建一个新的Downloader Middleware并记录您的所有请求(到文件或数据库).查看奇怪行为的请求.
  2. 限制深度以防止它无限地继续沿着兔子洞延伸.
  3. 限制域以测试它是否仍然存在问题.

如果您发现合法地仅生成许多请求,并且内存是一个问题,请启用持久作业队列并将请求保存到磁盘.不过,作为第一步,我建议不要这样做,因为你的抓取工具更有可能不像你想要的那样工作.