2017-07-11 22 views
0

我想爲密鑰異步查詢數據庫,然後向每個密鑰的多個URL發出請求。用於在多個請求中使用密鑰的異步查詢數據庫

我有一個函數從數據庫返回一個Deferred,它的值是幾個請求的關鍵字。理想情況下,我會調用這個函數並從start_requests返回一個Deferreds生成器。

@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): 
    ???? 

但嘗試這幾種方式提高

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

我採取意味着start_requests必須返回Request對象,而不是Deferreds其值爲Request對象。蜘蛛中間件的process_start_requests()也是如此。

或者,我可以向http://localhost/發起初始請求,並在通過下載器中間件的process_request()從數據庫獲得密鑰後,將它們更改爲真實URL。但是,process_request只返回一個Request對象;使用密鑰不能產生請求到多個頁面:嘗試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對象沒有屬性'dont_filter''這是同樣的問題 - 'start_requests()'需要產生請求對象,而不是產生器。循環生成器的情況也是如此:https://dpaste.de/JoD5。你能澄清嗎? – Hatshepsut

+0

我想我明白你想要做什麼。我已經更新了答案,以澄清事情。 – AJPennster

0

您沒有提供異步數據庫查詢的用例是必需的。我假設你不能開始刮你的網址,除非你先查詢數據庫?如果是這種情況,那麼最好是同步執行查詢,迭代查詢結果,提取所需內容,然後生成Request對象。查詢數據庫異步查詢並沒有什麼意義,只是坐等待查詢完成。

+0

這是一個工作隊列。如果我一下子就完成了所有的工作,第二個連接就不會有任何問題。對於長期存在的問題,我認爲一次獲得一份工作是異步的,效率很高。 – Hatshepsut

+0

我不完全確定你想傳達什麼。你能提供更多的背景來解決你的問題,並可能提供更多的代碼 –