2017-06-12 7 views
1

Ich kratze http://www.sephora.com/lipstick mit Scrapy Crawlspider. Wie soll ich einrichten LinkExtractor, um alle Seiten zu verschrotten? `Wie gehe ich mit crawlspider zur nächsten Seite?

class SephoraSpider(CrawlSpider): 
name = "sephora" 
# custom_settings = {"IMAGES_STORE": '../images/sephora'} 

# allowed_domains = ["sephora.com/"] 

start_urls = [ 
    'http://www.sephora.com/lipstick' 
    # 'http://www.sephora.com/eyeshadow', 
    # 'http://www.sephora.com/foundation-makeup' 
] 

rules = (Rule(LinkExtractor(
      # restrict_xpaths='//*[@id="main"]/div[4]/div[5]/div[1]/div/div[2]/div[3]/div[7]', 
      allow=('sephora.com/') 
      ), 
     callback = 'parse_items', 
     follow =True),) 

def parse(self,response): 
    # category = ['lipstick'] 
    # for cat in category: 
    full_url = 'http://www.sephora.com/rest/products/?currentPage=1&categoryName=lipstick&include_categories=true&include_refinements=true' 
    my_request = scrapy.Request(full_url, callback = 'parse_items') 
    my_request.meta['page'] = {'to_replace':"currentPage=1"} 
    yield my_request 

def parse_items(self,response): 

    # cat_json = response.xpath('//script[@id="searchResult"]/text()').extract_first() 
    # all_url_data = json.loads(cat_json.encode('utf-8')) 
    # if "products" not in all_url_data: 
    #  return 
    # products = all_url_data['products'] 
    products = json.loads(response.body)['products'] 
    print(products) 
    for each_product in products: 
     link = each_product['product_url'] 
     full_url = "http://www.sephora.com"+link 
     name = each_product["display_name"] 
     if 'list_price' not in each_product['derived_sku']: 
      price = each_product['derived_sku']['list_price_max'] 
     else: 
      price = each_product['derived_sku']["list_price"] 
     brand = each_product["brand_name"] 
     item = ProductItem(
      name=name, 
      price=price, 
      brand=brand, 
      full_url=full_url, 
      category=response.url[23:]) 
     yield item 

    to_replace = response.meta['page']['to_replace'] 
    cat = response.meta['page']['category'] 
    next_number = int(to_replace.replace("currentPage=", "")) + 1 
    next_link = response.url.replace(
     to_replace, "currentPage=" + str(next_number)) 
    print(next_link) 
    my_request = scrapy.Request(
     next_link, 
     self.parse_items) 
    my_request.meta['page'] = { 
     "to_replace": "currentPage=" + str(next_number), 

    } 
    yield my_request 

ich jetzt diesen Fehler haben.

2017-06-12 12:43:30 [scrapy] DEBUG: Crawled (200) <GET http://www.sephora.com/rest/products/?currentPage=1&categoryName=lipstick&include_categories=true&include_refinements=true> (referer: http://www.sephora.com/makeup-cosmetics) 
2017-06-12 12:43:30 [scrapy] ERROR: Spider error processing <GET http://www.sephora.com/rest/products/?currentPage=1&categoryName=lipstick&include_categories=true&include_refinements=true> (referer: http://www.sephora.com/makeup-cosmetics) 
Traceback (most recent call last): 
    File "/Users/Lee/anaconda/lib/python2.7/site-packages/scrapy/utils/defer.py", line 45, in mustbe_deferred 
    result = f(*args, **kw) 
    File "/Users/Lee/anaconda/lib/python2.7/site-packages/scrapy/core/spidermw.py", line 48, in process_spider_input 
    return scrape_func(response, request, spider) 
    File "/Users/Lee/anaconda/lib/python2.7/site-packages/scrapy/core/scraper.py", line 145, in call_spider 
    dfd.addCallbacks(request.callback or spider.parse, request.errback) 
    File "/Users/Lee/anaconda/lib/python2.7/site-packages/twisted/internet/defer.py", line 299, in addCallbacks 
    assert callable(callback) 
AssertionError 
2017-06-12 12:43:30 [scrapy] INFO: Closing spider (finished) 

Antwort

2

Kurze Antwort: Nicht.

Lange Antwort: Ich würde es anders machen. Die Paginierungslinks geben keine neue Seite zurück. Stattdessen senden sie eine GET -Anforderung an diese URL:

http://www.sephora.com/rest/products/?currentPage=2&categoryName=lipstick&include_categories=true&include_refinements=true.

Ihre Netzwerke Registerkarte Prüfen und klicken Sie auf eine Paginierung Link: Networks-Tab

Hier können Sie die Anfrage sehen können und die Reaktion Ihres Browsers macht. In diesem Fall führt ein Klick auf einen Paginatino-Link zu einem JSON-Objekt, das alle auf der Seite angezeigten Produkte enthält.

Jetzt überprüfen Sie die Response -Tabelle der Anfrage. Unter products können Sie Zahlen von 0 bis 59 sehen, die die auf der Seite angezeigten Produkte sind, sowie alle Informationen über die Produkte, wie id, display_name und, oh, url.

Klicken Sie mit der rechten Maustaste auf die Anfrage und wählen Sie Open in a new tab, um die Antwort in Ihrem Browser zu sehen. Versuchen Sie nun, die items per page auf der Sephora-Homepage auf etwas anderes einzustellen. Du siehst was passiert? Das JSON-Objekt gibt jetzt weniger oder mehr Elemente zurück (abhängig davon, was Sie ausgewählt haben).

Was machen wir jetzt mit diesen Informationen?

Idealerweise würden wir in der Lage sein, das JSON-Objekt für jede Seite anzufordern (von simmply der Anfrage-URL von current_page=2 zu current_page=3 Ändern) direkt in unsere Spinne und folgen Sie den dort vorgesehenen URLS (unter products/n-product/product_url und dann kriechen die einzelnen Objekte (oder nur die Produktlisten extrahieren, wenn das ist, was Sie wollen).

zum Glück Scrapy (besser, Python) können Sie JSON-Objekte analysieren und tun, was Sie mit den analysierten Daten wollen. und zum Glück Sephora können Sie wählen, zeige alle Artikel pro Seite an, die die Anfrage-URL auf ändern

Was du tust ist yield Eine Anfrage an die URL, die das JSON-Objekt liefert und eine parse -Funktion definiert, die das Objekt verarbeitet.

Nur ein kurzes Beispiel, dass die URLs für jedes Produkt extrahieren und eine Anforderung an diese URL ergeben (Ich werde später ein detaillierteres Beispiel versuchen Sie zur Verfügung stellen):

import json 

data = json.loads(response.body) 
for product in data["products"]: 
    url = response.urljoin(product["product_url"]) 
    yield scrapy.Request(url=url, callback=self.parse_products) 

Da haben Sie es. Es lohnt sich wirklich zu lernen, Anfragen an eine Webseite zu richten, da Sie die Anfrage-URL leicht manipulieren können, um Ihnen das Leben zu erleichtern. Beispielsweise könnten Sie die categoryName in der URL ändern, um eine andere Kategorie zu analysieren.

+0

Ich habe gerade meinen Code hinzugefügt, um Produkte zu schaben. Wenn ich diese Funktion behalte und sie in parse_products umwandle, muss ich parse_start_url hinzufügen, die sich mit http://www.sephora.com/rest/products/ beschäftigt?currentPage = 1 & categoryName = Lippenstift und include_categories = true & include_refinements = true, oder? –

+0

Korrekt, Sie brauchen grundsätzlich eine Parse-Funktion, die die Anfrage an das json-Objekt generiert, eine, die es analysiert und eine, die die einzelnen Produkt-URLs behandelt. – rongon

+0

Ich habe gerade meinen Code geändert, aber es scheint nicht zu funktionieren, nicht einmal die erste Seite –

Verwandte Themen