Ускорьте скребок

Я очищаю 23770 веб-страниц с помощью довольно простого веб-скребка, используя scrapy. Я совершенно новичок в scrapy и даже python, но сумел написать паука, который выполняет эту работу. Это, однако, очень медленно (требуется около 28 часов для сканирования 23770 страниц).

Я просмотрел веб-страницу scrapy и списки рассылки и stackoverflow, но я не могу найти общие рекомендации для написания быстрых сканеров, понятных для новичков. Может быть, моя проблема не в самом паук, а в том, как я ее запускаю. Все предложения приветствуются!

Я перечислил свой код ниже, если это необходимо.

from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector
from scrapy.item import Item, Field
import re

class Sale(Item):
    Adresse = Field()
    Pris = Field()
    Salgsdato = Field()
    SalgsType = Field()
    KvmPris = Field()
    Rum = Field()
    Postnummer = Field()
    Boligtype = Field()
    Kvm = Field()
    Bygget = Field()

class HouseSpider(BaseSpider):
    name = 'House'
    allowed_domains = ["http://boliga.dk/"]
    start_urls = ['http://www.boliga.dk/salg/resultater?so=1&type=Villa&type=Ejerlejlighed&type=R%%C3%%A6kkehus&kom=&amt=&fraPostnr=&tilPostnr=&iPostnr=&gade=&min=&max=&byggetMin=&byggetMax=&minRooms=&maxRooms=&minSize=&maxSize=&minsaledate=1992&maxsaledate=today&kode=&p=%d' %n for n in xrange(1, 23770, 1)]

    def parse(self, response):
        hxs = HtmlXPathSelector(response)
        sites = hxs.select("id('searchresult')/tr")
        items = []      
        for site in sites:
            item = Sale()
            item['Adresse'] = site.select("td[1]/a[1]/text()").extract()
            item['Pris'] = site.select("td[2]/text()").extract()
            item['Salgsdato'] = site.select("td[3]/text()").extract()
            Temp = site.select("td[4]/text()").extract()
            Temp = Temp[0]
            m = re.search('\r\n\t\t\t\t\t(.+?)\r\n\t\t\t\t', Temp)
            if m:
                found = m.group(1)
                item['SalgsType'] = found
            else:
                item['SalgsType'] = Temp
            item['KvmPris'] = site.select("td[5]/text()").extract()
            item['Rum'] = site.select("td[6]/text()").extract()
            item['Postnummer'] = site.select("td[7]/text()").extract()
            item['Boligtype'] = site.select("td[8]/text()").extract()
            item['Kvm'] = site.select("td[9]/text()").extract()
            item['Bygget'] = site.select("td[10]/text()").extract()
            items.append(item)
        return items

Спасибо!

Ответ 1

Здесь собраны вещи, которые нужно попробовать:

  • используйте последнюю версию scrapy (если не используете уже)
  • проверьте, используются ли нестандартные средние страницы
  • попытайтесь увеличить настройки CONCURRENT_REQUESTS_PER_DOMAIN, CONCURRENT_REQUESTS (docs)
  • отключить ведение журнала LOG_ENABLED = False (docs)
  • попробуйте yield вставить элемент в цикле вместо того, чтобы собирать элементы в список items и возвращать их
  • использовать локальный кеш-DNS (см. этот поток)
  • проверьте, использует ли этот сайт порог загрузки и ограничивает скорость загрузки (см. этот поток)
  • log cpu и использование памяти во время запуска паука - посмотрите, есть ли там проблемы.
  • попробуйте запустить тот же паук в scrapyd service
  • посмотрим, если grequests + lxml (спросите, нужна ли вам какая-либо помощь в реализации этого решения).
  • попробуйте запустить Scrapy на pypy, см. Запуск Scrapy на PyPy

Надеюсь, что это поможет.

Ответ 2

Глядя на ваш код, я бы сказал, что большая часть времени тратится на сетевые запросы, а не на обработку ответов. Все советы, которые @alecxe предоставляет в своем ответе, применяются, но я бы предложил настройку HTTPCACHE_ENABLED, так как он кэширует запросы и избегает делать это во второй раз. Это помогло бы при следующих обходах и даже в автономном режиме. Подробнее см. В документах: http://doc.scrapy.org/en/latest/topics/downloader-middleware.html#module-scrapy.contrib.downloadermiddleware.httpcache

Ответ 3

Я также работаю на веб-утилизации, используя оптимизированный С#, и он заканчивается загрузкой процессора, поэтому я переключаюсь на C.

Анализ HTML удаляет кэш данных ЦП и почти уверен, что ваш процессор не использует SSE 4.2 вообще, поскольку вы можете получить доступ только к этой функции с помощью C/С++.

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