2016-05-10 8 views
0

私はscraping thisを使用してこのsiteを使用しています。私は、対応するページ(ページネーション)を取得し、その後、アレイ内のすべてのサブカテゴリーを保存したいPythonで再帰非同期ジョブを終了した後に関数を呼び出す方法は?


私は

def start_requests(self): 
     yield Request(start_urls[i], callback=self.get_sous_cat) 

get_sous_catはすべて取得する機能である持っている最初のステップは、そのサブカテゴリを再帰的に探索するために非同期的にジョブを開始する。すべてそれぞれの要求が送られてきた

def get_sous_cat(self,response): 
    #Put all the categgories in a array 
    catList = response.css('div.categoryRefinementsSection') 
    if (catList): 
     for category in catList.css('a::attr(href)').extract(): 
      category = 'https://www.amazon.fr' + category 
      print category 
      self.arrayCategories.append(category) 
      yield Request(category, callback=self.get_sous_cat) 

、私はこの終了関数を呼び出す必要があります。

def pagination(self,response): 
    for i in range(0, len(self.arrayCategories[i])): 
     #DO something with each sub-category 

を私はこれは "再帰" ではありません。この

def start_requests(self): 

    yield Request(start_urls[i], callback=self.get_sous_cat) 

    for subCat in range(0,len(self.arrayCategories)): 
     yield Request(self.arrayCategories[subCat], callback=self.pagination) 
+0

「これ」を試しましたが、結果は何ですか?あなたの期待とどのように違うのですか? – Psytho

+0

完全に、擦り傷が終わったときを意味しますか?それはあなたのコードのaxampleからのようです。 spider_closedシグナルに接続することもできます。http://doc.scrapy.org/ja/latest/topics/signals.html#spiderclosedを参照してください。ページネーションルーチンで何をしているのかについてもっと説明できますか?このリンクの – Steve

+0

https://www.amazon.fr/s/ref=sr_nr_n_0?fst=as%3Aoff&rh=n%3A3635788031%2Cp_76%3A437878031%2Cp_6%3AA1X6FK5RDHNB96%2Cn%3A!3635789031%2Cn%3A6356706031&bbn = 3635789031&ie = UTF8&qid = 1462896936&rnid = 3635789031私たちは17ページのカテゴリを持っています。私たちはRepasのようなサブカテゴリを持っています。このページのURL + RepasのようなサブカテゴリーのURLを配列、ページ区切り機能でカテゴリの17ページを取得します – parik

答えて

2

さて、これは良い質問です! 2つの小さなもの:

a)配列の代わりにセットを使用します。この方法では重複はありません b)サイト構造は月に1回変更されます。あなたはたぶん頻繁にクロールします。スパイダーを2つに分割する。 1.カテゴリURLのリストを作成して毎月実行するもの2.最初に生成されたファイルをstart_urlsとして取得するもの

今、あなたが本当にやりたければ、フックspider_idleシグナル(Scrapy: How to manually insert a request from a spider_idle event callback?参照)。それ以上のURLがないときに呼び出され、より多くの情報を注入することができます。フラグを設定するか、その時点でリストをリセットして、スパイダーがアイドル状態(すべてをクロールした後)で、同じカテゴリのURLをいつも再注入しないようにします。

あなたの場合のように、URLでいくつかの気の利いた処理をしたくない場合は、他のURLより前にカテゴリをクロールするだけです。これは、(http://doc.scrapy.org/en/latest/topics/request-response.html#topics-request-response-ref-request-subclasses)のリクエスト優先プロパティです。たとえばに設定してください。 1をカテゴリURLとして使用し、カテゴリ以外のリンクを処理する前にそれらのリンクに従います。これは、現在の実装のようにカテゴリページを2回読み込まないため、より効率的です。

+0

優れた答えは、私が今治療について知っている2つの新しいことです、ありがとうございます。 – Steve

1

を試してみました、それは非同期ジョブです。何が必要(ロックにより保護)グローバルカウンタで、0ならば、あなたの補完を行います。counter -= 1

を行い、

from threading import Lock 

class JobCounter(object): 
    def __init__(self, completion_callback, *args, **kwargs): 
     self.c = 0 
     self.l = Lock() 
     self.completion = (completion_callback, args, kwargs) 
    def __iadd__(self, n): 
     b = false 
     with self.l: 
     self.c += n 
     if self.c <= 0: 
      b = true 
     if b: 
     f, args, kwargs = self.completion 
     f(*args, **kwargs) 
    def __isub__(self, n): 
     self.__iadd__(-n) 

ジョブを起動するたびに、counter += 1

ジョブが終了するたびに行います

注:最後の呼び出しジョブのスレッドで完了します。特定のスレッドで実行したい場合は、Lockの代わりにConditionを使用し、呼び出しの代わりにnotify()を実行します。

+1

あなたはScrapyでロックが必要かどうかわかりません:-)それはほとんどがツイスト/シングルスレッドです。 – neverlastn

関連する問題