python - Scrapy 蜘蛛内存泄漏

标签 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)

这里是 prefs() 的输出

HtmlResponse                        2   oldest: 0s ago 
ExternalLinkSpider                  1   oldest: 3285s ago
LinkCrawlItem                       2   oldest: 0s ago
Request                        1663405   oldest: 3284s ago

100k 抓取页面的内存在某些网站上可以达到 40gb 标记(例如在 victorinox.com,它在 100k 抓取页面标记时达到 35gb 内存)。另一方面,它要小得多。

更新。

Objgraph for oldest request after some time of run

enter image description here

最佳答案

我立即发现了一些可能的问题。

不过在开始之前,我想提一下 prefs() 不显示排队的请求数,它显示事件的 Request() 对象的数量。可以引用请求对象并使其保持事件状态,即使它不再排队等待下载也是如此。

虽然我在您提供的代码中没有真正看到任何会导致此问题的内容,但您应该牢记这一点。

马上,我会问:你在使用 cookies 吗?否则,将 session ID 作为 GET 变量传递的站点将为每次页面访问生成一个新的 session ID。您基本上会一遍又一遍地继续排队相同的页面。例如,victorinox.com 的 URL 字符串中将包含类似“jsessionid=18537CBA2F198E3C1A5C9EE17B6C63AD”的内容,每次加载新页面时 ID 都会发生变化。

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

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

不过,您需要进行更多故障排除才能准确了解发生了什么。

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

  1. 创建一个新的下载器中间件并记录您的所有请求(到文件或数据库)。查看针对异常行为的请求。
  2. 限制 Depth 以防止它无限地继续进入兔子洞。
  3. 限制域以测试它是否仍然存在问题。

如果您发现您合法地只是生成许多请求,并且内存是一个问题,请启用持久作业队列并将请求保存到磁盘。不过,我建议不要将此作为第一步,因为您的抓取工具更有可能无法按您希望的方式工作。

关于python - Scrapy 蜘蛛内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31594090/

相关文章:

c# - 使用它的指针从托管 C# 中释放非托管内存

python - 我正在尝试打印 scrapy 请求的 301 状态。但是,页面每次都会重定向并显示200

python - level必须是整数,elasticsearch报错

python - Scrapy 部署与调试结果不匹配

python - Mongoengine - 如何执行 "save new item or increment counter"操作?

python - __file__ 和 os.path 模块运行不正常?

python - 从 HTML 页面中删除样板内容

python - 如何最好地将 NetCDF 文件集合重新分块到 Zarr 数据集

java - Java Enterprise 应用程序中的类加载问题

c++ - 用于查找指针何时超出范围的程序和技术