2017-06-12 14 views
1

私はscrapy crawlspiderを使用してhttp://www.sephora.com/lipstickを掻いています。私は今、このエラーを持っているどのように私はすべてのページをスクラップするためにLinkExtractorを設定する必要がありますか? `crawlspiderを使って次のページに移動するには?

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 

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) 

答えて

2

短い回答:しないでください。

長い答え:私は別のやり方をします。ページネーションリンクは新しいページを返しません。代わりに、GET -requestを次のURLに送信します。

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

は、あなたのネットワーク]タブを確認し、ページネーションのリンクをクリックしてください:ここでNetworks-Tab

、あなたのブラウザが行うリクエストとレスポンスを見ることができます。この場合、paginatinoリンクをクリックすると、ページに表示されているすべての製品が含まれたJSONオブジェクトが生成されます。

リクエストのResponseタップを確認してください。 productsの下には、id,display_name、およびurlなど、製品に記載されているすべての情報と同様に、ページに表示される製品である0から59までの数字が表示されます。

リクエストを右クリックしてOpen in a new tabを選択して、ブラウザでレスポンスを確認してください。 sephora-homepageのitems per pageを別のものに設定してみてください。あなたは何が起こるかを見ますか? JSONオブジェクトは、(選択した内容に応じて)現在より少ないまたはより多くのアイテムを返します。

ここでこの情報をどうしたらいいですか?

理想的には、私たちがクモに直接(simmply current_page=3current_page=2から要求URLを変更して)各ページのJSONオブジェクトを要求することができるとURLをたどるには、products/n-product/product_url下(が提供して、個々のオブジェクトをクロールあなたが望むなら製品リストを抽出してください。

Scaff(better、Python)は、JSONオブジェクトを解析し、解析されたデータで必要な処理を行うことができます。ページあたりのすべてのアイテムを表示すると、リクエストはURL:?pageSize=-1に変更されます。

何をしていますかyield JSONオブジェクトを生成するurlへの要求を行い、オブジェクトを処理するparse関数を定義します。各製品のURLを抽出し、このURLへのリクエストが得られます

だけで簡単に例では、(私は後でより詳細な例を提供しますしようとします):あり

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) 

あなたはそれを持っています。あなたの人生をより簡単にするためのリクエストURLを簡単に操作できるように、ウェブサイトにリクエストを出すことを学ぶのは本当にお得です。たとえば、URLのcategoryNameを変更して、別のカテゴリを解析することができます。

+0

私はスクラップ製品に自分のコードを追加しました。この機能を維持してparse_productsに変更すると、http://www.sephora.com/rest/products/を扱うparse_start_urlを追加する必要がありますか?currentPage = 1&categoryName = lipstick&include_categories = true&include_refinements = true、そうですか? –

+0

正直なところ、基本的には、jsonオブジェクトへのリクエストを生成するparse-function、それを解析するリクエスト、個々のproduct-urlsを処理するリクエストが必要です。 – rongon

+0

私のコードを変更したばかりですが、最初のページでさえも動作しないようです。 –

関連する問題