python - tutorial - 用於在多個請求中使用密鑰的異步查詢數據庫




scrapy url (2)

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

我想異步查詢一個數據庫的鍵,然後請求每個鍵的幾個網址。

我有一個函數從數據庫返回一個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) :試圖yield Request(url)引發

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

什麼是最乾淨的解決方案

  • 從數據庫異步獲取密鑰
  • 為每個密鑰生成幾個請求

你可以讓Deferred對象的回調傳遞給某種類型的生成器。 生成器然後將所有收到的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

當你完成時,不要忘記停止請求發生器。





twisted