2015-07-23 3 views
12

У моего паука серьезная утечка памяти. Через 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) 

Здесь выход префов()

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

памяти для 100k Царапины страницы могут ударить 40gb отметки на некоторых сайтах (например, на victorinox.com это до 35 ГБ памяти на отметке 100 тыс. царапин). На другом его гораздо меньше.

UPD.

Objgraph for oldest request after some time of run

enter image description here

ответ

7

Есть несколько возможных вопросов, которые я вижу сразу.

Прежде чем начать, я хотел бы упомянуть, что prefs() не показывает количество запросов в очереди, оно показывает количество объектов Request(), которые находятся в живых. Можно ссылаться на объект запроса и поддерживать его, даже если он больше не загружается в очередь.

Я действительно ничего не вижу в коде, который вы предоставили, который может вызвать это, хотя вы должны помнить об этом.

С самого начала, я бы спросил: вы используете куки? Если нет, сайты, которые передают идентификатор сеанса в виде переменной GET, будут генерировать новый идентификатор сеанса для каждого посещения страницы. Вы по существу продолжаете поочередно повторять одни и те же страницы. Например, у victorinox.com будет что-то вроде «jsessionid = 18537CBA2F198E3C1A5C9EE17B6C63AD» в строке URL-адреса, с изменением идентификатора для каждой новой загрузки страницы.

Во-вторых, вы можете поразить пауков-пауков. То есть, страница, которая просто перезагружается, с новым бесконечным количеством ссылок. Подумайте о календаре со ссылкой на «следующий месяц» и «предыдущий месяц». Тем не менее, я не вижу прямого доступа на сайте victorinox.com.

В-третьих, из предоставленного кода ваш Паук не ограничен каким-либо конкретным доменом. Он будет извлекать каждую найденную ссылку на каждой странице, используя parse_obj на каждой странице. На главной странице сайта victorinox.com есть ссылка на http://www.youtube.com/victorinoxswissarmy. Это, в свою очередь, заполнит ваши запросы множеством ссылок на YouTube.

Вам нужно будет устранить проблему, чтобы узнать, что именно происходит.

Некоторые стратегии, которые вы можете захотеть использовать:

  1. Создать новую Downloader Middleware и регистрировать все ваши запросы (в файл или базу данных). Просмотрите запросы на нечетное поведение.
  2. Ограничьте глубину, чтобы предотвратить непрерывное продолжение кроличьей дыры.
  3. Ограничьте домен, чтобы проверить, если это все еще проблема.

Если вы считаете, что являетесь законным источником многих запросов, а проблема с памятью, включите постоянную очередь заданий и сохраните запросы на диск. Я бы рекомендовал против этого как первый шаг, хотя, скорее всего, ваш искатель не работает так, как вы этого хотели.

+0

В-третьих - мой код ограничен одним доменом. Но домен может быть любым. Im настраивает разрешенные домены динамически, поэтому im захватывает только один домен за раз. Что касается печенья - хорошая точка. Постоянная очередь - я сказал в группе пользователей scrapy, что они очень медленны с большим количеством запросов, поэтому его не вариант :( – Aldarund

+0

Хорошо, что не было показано в вашем коде, поэтому я упоминал об этом! Постоянная очередь медленный, хотя, и он больше подходит для приостановки/возобновления очередей. Я считаю, что разница в скорости действительно является памятью против диска. – Rejected

+0

Я даже установил очередь FifoMemoryQueue, но все же самый старый объект запроса почти такой же старый, как у паука объект. Не должен ли он быть обработан и освобожден? – Aldarund