2017-07-11 9 views
0

データベースに対して非同期にキーを照会し、各キーの複数のURLへのリクエストを行いたいとします。複数のリクエストで使用するキーの非同期クエリデータベース

私は、値がいくつかのリクエストのキーであるデータベースからDeferredを返す関数を持っています。理想的には、私はこの関数を呼び出して、Deferredsのジェネレータをstart_requestsから返します。

@inlineCallbacks 
def get_request_deferred(self): 

    d = yield engine.execute(select([table])) # async 
    d.addCallback(make_url) 
    d.addCallback(Request) 
    return d 

def start_requests(self): 
    ???? 

しかし、いくつかの方法でこれをしようとは、私はstart_requestsRequestオブジェクトではなく、その値RequestオブジェクトであるのDeferredを返さなければならないことを意味すると取る

builtins.AttributeError: 'Deferred' object has no attribute 'dont_filter' 

を発生させます。スパイダーミドルウェアのprocess_start_requests()も同様です。

また、http://localhost/などの初期リクエストを作成し、ダウンローダミドルウェアのprocess_request()を使用してデータベースからキーを入手すると、実際のURLに変更することができます。ただし、process_requestRequestオブジェクトのみを返します。それは、キーを使用して複数のページに要求を得られないことができます:yield Request(url)をしようとすると、

  • にきれいな解決策は、各キーのデータベース
  • から非同期キーを取得されて何

    AssertionError: Middleware myDownloaderMiddleware.process_request 
    must return None, Response or Request, got generator 
    

    を発生させ、いくつかの要求

  • を生成します
+0

http://techspot.zzzeek.org/2015/02/15/asynchronous-python-and-databases/ – MishaVacic

答えて

0

Deferredオブジェクトのコールバックに、ある種のジェネレータにURLを渡すことができます。ジェネレータは受信したURLをscrapy Requestオブジェクトに変換して返します。以下は(テストしていません)あなたがリンクされたコードを使用した例です。

import scrapy 
from Queue import Queue 
from pdb import set_trace as st 
from twisted.internet.defer import Deferred, inlineCallbacks 


class ExampleSpider(scrapy.Spider): 
    name = 'example' 

    def __init__(self): 
     self.urls = Queue() 
     self.stop = False 
     self.requests = request_generator() 
     self.deferred = deferred_generator() 

    def deferred_generator(self): 
     d = Deferred() 
     d.addCallback(self.deferred_callback) 
     yield d 

    def request_generator(self): 
     while not self.stop: 
      url = self.urls.get() 
      yield scrapy.Request(url=url, callback=self.parse) 

    def start_requests(self): 
     return self.requests.next() 

    def parse(self, response): 
     st() 

     # when you need to parse the next url from the callback 
     yield self.requests.next() 

    @static_method 
    def deferred_callback(url): 
     self.urls.put(url) 
     if no_more_urls(): 
      self.stop = True 

が完了したら、要求生成を停止することを忘れないでください。

+0

私はあなたが何を意味しているか分かりません。このコードhttps://dpaste.de/LpvQでは、 'generatorオブジェクトには属性がありません 'という同じ問題があります。' start_requests() 'はジェネレータではなくリクエストオブジェクトを生成する必要があります。発電機のルーピングについても同じことが言えます:https://dpaste.de/JoD5。明確にすることはできますか? – Hatshepsut

+0

私はあなたがしたいことを理解していると思います。私は物事をクリアするための答えを更新しました。 – AJPennster

0

非同期データベースクエリが必要であるというユースケースはありません。データベースを最初に照会しない限り、URLを傷つけ始めることはできないと思いますか?そうであれば、クエリを同期して実行し、クエリ結果を繰り返し処理し、必要なものを抽出してから、Requestオブジェクトを生成するほうがよいでしょう。 dbを非同期的に照会し、照会が完了するのを待っているだけではほとんど意味がありません。

+0

これはジョブキューです。私が一度にすべての仕事を得れば、2番目の接続に残ることはありません。長時間の作業では、一度に1つの仕事(async)を得ることはかなり効率的です。 – Hatshepsut

+0

あなたが伝えようとしていることは完全にはわかりません。問題の内容をより詳細に把握し、試したことのあるコードを提供することは可能でしょうか –

関連する問題