Я строю скребок, который должен очищать изображения и кусочки информации о продуктах, найденных на Houzz.com. У меня есть ~ 460 стартовых URL, которые являются сетками продуктов, и я go для всех последующих страниц (нумерация страниц), чтобы сканировать все продукты. Я захожу на страницы продукта, чтобы получить некоторую информацию и одно изображение продукта.
При запуске моего паука у меня заканчивается память в течение нескольких минут, хотя я запускаю его на экземпляре EC2 с 32 ГБ памяти. Я просматривал некоторые страницы об утечках памяти на веб-сайтах Scrapy Docs, но не могу понять, почему у моего паука так мало памяти.
Я уже использую "-s" JOBDIR = crawls / houzz_spider "аргумент при сканировании. При взгляде на prefs () запросы, кажется, не взрываются, когда паук все еще работает, а у экземпляра еще не исчерпана память.
Кроме этого, я открываю некоторые txt-файлы в начале выполнения и напишите им URL-адреса, сведения о которых не могут быть найдены в данный момент. В случае, если это может иметь какое-либо отношение к этому ...
Мой паук (избавился от некоторых переменных, которые не являются):
import boto3
from boto3.dynamodb.conditions import Key
import logging
class HouzzSpider(scrapy.Spider):
name = 'houzz_spider'
log_file = open(LOG_FILENAME, "w+")
left_file = open(LEFT_FILENAME, "w+")
dup_file = open(DUP_FILENAME, "w+")
logging.basicConfig(
filename=CRAWLER_LOG_FILENAME,
)
wait = 4
allowed_domains = ["www.houzz.com"]
start_urls_file = 'start_urls.txt'
product_page_url_selector = ".hz-product-card__link::attr(href)"
product_name_selector = "h1.product-title::text"
main_product_image_selector = "img.view-product-image-print::attr(src)"
product_description_selector = "#productDescription *::text"
price_selector = ".product-final-price::text"
n_products_claimed_selector = ".hz-top-pagination__text > b::text"
cats_dict = {}
# AWS DynamoDB
dynamodb = boto3.resource(...)
table = dynamodb.Table('my-table')
def get_product_grid_pages(self):
f = open(self.start_urls_file, "r")
cats_dict = {}
for cat in f:
if 'https' in cat:
if '\n' in cat:
cat = cat.split('\n')[0]
cats_dict[cat] = {'n_products_claimed' : None, # N products the website claims there are
'n_product_pages_counted': 0, # N product pages visited
'n_items_yielded': 0, # N items returned
'n_overview_pages_counted': 0, # Overview pages visited
'n_pages_claimed': 1000} # N pages the website claims there are
return cats_dict
def start_requests(self):
self.cats_dict = self.get_product_grid_pages()
print("\n CATS:", list(self.cats_dict.keys()), '\n')
for product_grid_url in list(self.cats_dict.keys()):
yield SplashRequest(url=product_grid_url, callback=self.parse, args={"wait": self.wait})
def parse(self, response):
for item in self.scrape_overview_page(response):
yield item
def parse_product_page(self, response):
print("Start parsing product page...", response.url)
furniture_item = response.meta['furniture_item']
# PRODUCT NAME
product_name = response.css(self.product_name_selector).extract_first()
furniture_item['product_name'] = product_name
if product_name != None:
# Check if product is already in DB
resp = self.table.query(
KeyConditionExpression=Key('product_name').eq(product_name)
)
# Item does not exist yet
if len(resp['Items']) == 0:
# PRODUCT DESCRIPTION
furniture_item['product_description'] = " ".join(response.css(self.product_description_selector).extract())
furniture_item['price'] = response.css(self.price_selector).extract_first()
# IMAGES
furniture_item['image_urls'] = response.css(self.main_product_image_selector).extract()
if (len(furniture_item['image_urls']) > 0) and (product_name != None):
yield furniture_item
else:
print('DUPLICATE')
else:
print('NONE as PRODUCT NAME')
def scrape_overview_page(self, response):
n_products_claimed_text_list = response.css(self.n_products_claimed_selector).extract()
if '/p' in response.url:
cat = response.url.split('/p/')[0]
else:
cat = response.url
# LINKS TO PRODUCT PAGES
product_page_urls = list(set(response.css(self.product_page_url_selector).extract()))
N = len(product_page_urls)
# RETRIEVE PRODUCTS
for i in range(N):
# INIT ITEM
furniture_item = Houzz_Furniture_Item()
furniture_item['product_page_url'] = product_page_urls[i]
furniture_item['category'] = cat
# Load product page with Splash
product_page_request = SplashRequest(url=product_page_urls[i], callback=self.parse_product_page, args={"wait":self.wait})
product_page_request.meta['furniture_item'] = furniture_item
# Return the item + product details and images found on product page back to parser
yield product_page_request
# GO TO NEXT PAGE
i = self.cats_dict[cat]['n_product_pages_counted']
if i < self.cats_dict[cat]['n_pages_claimed']:
next_page_full_url = cat + '/p/' + str(i)
yield SplashRequest(url=next_page_full_url, callback=self.scrape_overview_page, args={"wait":self.wait})
Мои настройки:
#####################################
# S3 #
#####################################
# IMAGES_STORE = MY S3 BUCKET
BOT_NAME = 'houzz_spider'
SPIDER_MODULES = ['furniture_scraper.spiders']
NEWSPIDER_MODULE = 'furniture_scraper.spiders'
# ALLOW DUPLICATES: FALSE (needed for different colours of same furniture item)
DUPEFILTER_CLASS = 'scrapy.dupefilters.BaseDupeFilter'
#####################################
# FOR USING SPLASH #
#####################################
SPLASH_URL = 'http://localhost:8050'
DOWNLOADER_MIDDLEWARES = {
'scrapy_splash.SplashCookiesMiddleware': 723,
'scrapy_splash.SplashMiddleware': 725,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}
SPIDER_MIDDLEWARES = {
'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
}
HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'
#####################################
# USING THE IMAGES PIPELINE #
#####################################
ITEM_PIPELINES = {
'furniture_scraper.pipelines.FurnitureImagePipeline': 1,
'furniture_scraper.pipelines.DynamoDbPipeline': 1
}
IMAGES_URLS_FIELD = 'image_urls'
IMAGES_RESULT_FIELD = 'images'
#####################################
# AWS ACCESS #
#####################################
# MY CREDENTIALS
#####################################
# AWS dynano db #
#####################################
# MY DB
#####################################
# DEBUG #
#####################################
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36'
MEMUSAGE_ENABLED = 1
MEMUSAGE_LIMIT_MB = 1024
CONCURRENT_REQUESTS = 100
Если бы кто-то мог указать мне правильное направление, это было бы здорово.
Заранее спасибо!