Ускорьте скребок
Я очищаю 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/С++.
Если вы выполняете математику, вы быстро вычисляете привязку, но не привязываетесь к памяти.