2016-07-24 47 views
1

なぜ私のスパイダーが機能しないのか迷っています!私はではないはプログラマーを意味するので、親切にしてください!笑Scrapy:カスタムコールバックが機能しない

背景: 私は「Scrapy」の使用とインディゴで見つかった図書に関連する情報をこすりしようとしています。

問題:は 私のコードは私のカスタムコールバックのいずれかを入力していない...私がコールバックとして「解析」を使用する場合にのみ動作するようです。

コードの "Rules"セクションのコールバックを "parse_books"から "parse"に変更すると、すべてのリンクのリストを作成する方法がうまく動作し、すべてが印刷されますしかし、そのメソッド内のコールバック( "parse_books"を指す)は決して呼び出されません!奇妙なことに、 "parse"メソッドの名前を何か他のもの( "testmethod")に変更して "parse_books"メソッドの名前を "parse"に変更すると、のメソッドがのアイテムにスクラップしても問題ありません!

私が達成しようとしている何

私がしたいすべてが、ページを入力の「ベストセラー」を言わせて、すべての項目について、それぞれのアイテムレベルのページに移動し、すべてをこすりです本関連情報私は両者が独立して働いているようです:/

コード!

import scrapy 
import json 
import urllib 
from scrapy.http import Request 
from urllib import urlencode 
import re 
from scrapy.linkextractors import LinkExtractor 
from scrapy.spiders import CrawlSpider, Rule 
import urlparse 



from TEST20160709.items import IndigoItem 
from TEST20160709.items import SecondaryItem 



item = IndigoItem() 
scrapedItem = SecondaryItem() 

class IndigoSpider(CrawlSpider): 

    protocol='https://' 
    name = "site" 
    allowed_domains = [ 
    "chapters.indigo.ca/en-ca/Books", 
    "chapters.indigo.ca/en-ca/Store/Availability/" 
    ] 

    start_urls = [ 
     'https://www.chapters.indigo.ca/en-ca/books/bestsellers/', 
    ] 

    #extractor = SgmlLinkExtractor()s 

    rules = (
    Rule(LinkExtractor(), follow = True), 
    Rule(LinkExtractor(), callback = "parse_books", follow = True), 
    ) 



    def getInventory (self, bookID): 
     params ={ 
     'pid' : bookID, 
     'catalog' : 'books' 
     } 
     yield Request(
      url="https://www.chapters.indigo.ca/en-ca/Store/Availability/?" + urlencode(params), 
      dont_filter = True, 
      callback = self.parseInventory 
     ) 



    def parseInventory(self,response): 
     dataInventory = json.loads(response.body) 

     for entry in dataInventory ['Data']: 
      scrapedItem['storeID'] = entry['ID'] 
      scrapedItem['storeType'] = entry['StoreType'] 
      scrapedItem['storeName'] = entry['Name'] 
      scrapedItem['storeAddress'] = entry['Address'] 
      scrapedItem['storeCity'] = entry['City'] 
      scrapedItem['storePostalCode'] = entry['PostalCode'] 
      scrapedItem['storeProvince'] = entry['Province'] 
      scrapedItem['storePhone'] = entry['Phone'] 
      scrapedItem['storeQuantity'] = entry['QTY'] 
      scrapedItem['storeQuantityMessage'] = entry['QTYMsg'] 
      scrapedItem['storeHours'] = entry['StoreHours'] 
      scrapedItem['storeStockAvailibility'] = entry['HasRetailStock'] 
      scrapedItem['storeExclusivity'] = entry['InStoreExlusive'] 

      yield scrapedItem 



    def parse (self, response): 
     #GET ALL PAGE LINKS 
     all_page_links = response.xpath('//ul/li/a/@href').extract() 
     for relative_link in all_page_links: 
      absolute_link = urlparse.urljoin(self.protocol+"www.chapters.indigo.ca",relative_link.strip()) 
      absolute_link = absolute_link.split("?ref=",1)[0] 
      request = scrapy.Request(absolute_link, callback=self.parse_books) 
      print "FULL link: "+absolute_link 

      yield Request(absolute_link, callback=self.parse_books) 





    def parse_books (self, response): 

     for sel in response.xpath('//form[@id="aspnetForm"]/main[@id="main"]'): 
      #XML/HTTP/CSS ITEMS 
      item['title']= map(unicode.strip, sel.xpath('div[@class="content-wrapper"]/div[@class="product-details"]/div[@class="col-2"]/section[@id="ProductDetails"][@class][@role][@aria-labelledby]/h1[@id="product-title"][@class][@data-auto-id]/text()').extract()) 
      item['authors']= map(unicode.strip, sel.xpath('div[@class="content-wrapper"]/div[@class="product-details"]/div[@class="col-2"]/section[@id="ProductDetails"][@class][@role][@aria-labelledby]/h2[@class="major-contributor"]/a[contains(@class, "byLink")][@href]/text()').extract()) 
      item['productSpecs']= map(unicode.strip, sel.xpath('div[@class="content-wrapper"]/div[@class="product-details"]/div[@class="col-2"]/section[@id="ProductDetails"][@class][@role][@aria-labelledby]/p[@class="product-specs"]/text()').extract()) 
      item['instoreAvailability']= map(unicode.strip, sel.xpath('//span[@class="stockAvailable-mesg negative"][@data-auto-id]/text()').extract()) 
      item['onlinePrice']= map(unicode.strip, sel.xpath('//span[@id][@class="nonmemberprice__specialprice"]/text()').extract()) 
      item['listPrice']= map(unicode.strip, sel.xpath('//del/text()').extract()) 

      aboutBookTemp = map(unicode.strip, sel.xpath('//div[@class="read-more"]/p/text()').extract()) 
      item['aboutBook']= [aboutBookTemp] 

      #Retrieve ISBN Identifier and extract numeric data 
      ISBN_parse = map(unicode.strip, sel.xpath('(//div[@class="isbn-info"]/p[2])[1]/text()').extract()) 
      item['ISBN13']= [elem[11:] for elem in ISBN_parse] 
      bookIdentifier = str(item['ISBN13']) 
      bookIdentifier = re.sub("[^0-9]", "", bookIdentifier) 


      print "THIS IS THE IDENTIFIER:" + bookIdentifier 

      if bookIdentifier: 
       yield self.getInventory(str(bookIdentifier)) 

      yield item 
+0

あなたのメソッドはクラス外のようです。コードをフォーマットできますか? – masnun

答えて

1

私が気づいた最初の動機の1つは、あなたのallowed_domainsクラス属性が壊れていることです。 ドメイン(したがって名前)を含める必要があります。あなたのケースで

正しい値は次のようになります。

起こるべきではありません
DEBUG: Filtered offsite request to 'www.chapters.indigo.ca' 

を:

allowed_domains = [ 
    "chapters.indigo.ca", # subdomain.domain.top_level_domain 
] 

あなたのクモをチェックすると、あなたが見るであろうログ。

+0

ありがとう!それは働いているようだ! "parseInventory"メソッドはトリガされていないようですが、あなたは確実にその日を保存しました。私はそれを深く感謝します! –

+0

あなたの問題を解決することが判明した場合は問題はありません。 – Granitosaurus

+0

もう一度やり直してください! –

関連する問題