我的蜘蛛有严重的内存泄漏。运行 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 内存)。另一方面,它要小得多。
更新。
最佳答案
我立即发现了一些可能的问题。
不过在开始之前,我想提一下 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 链接填满您的请求。
不过,您需要进行更多故障排除才能准确了解发生了什么。
您可能想使用的一些策略:
- 创建一个新的下载器中间件并记录您的所有请求(到文件或数据库)。查看针对异常行为的请求。
- 限制 Depth 以防止它无限地继续进入兔子洞。
- 限制域以测试它是否仍然存在问题。
如果您发现您合法地只是生成许多请求,并且内存是一个问题,请启用持久作业队列并将请求保存到磁盘。不过,我建议不要将此作为第一步,因为您的抓取工具更有可能无法按您希望的方式工作。
关于python - Scrapy 蜘蛛内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31594090/