Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 用于在多个请求中使用的密钥的异步查询数据库_Python_Database_Asynchronous_Scrapy_Twisted - Fatal编程技术网

Python 用于在多个请求中使用的密钥的异步查询数据库

Python 用于在多个请求中使用的密钥的异步查询数据库,python,database,asynchronous,scrapy,twisted,Python,Database,Asynchronous,Scrapy,Twisted,我想异步查询数据库中的密钥,然后为每个密钥请求几个URL 我有一个函数,它从数据库返回一个延迟的,该数据库的值是多个请求的键。理想情况下,我会调用此函数并返回一个从start\u请求推迟的生成器 @inlineCallbacks def get_request_deferred(self): d = yield engine.execute(select([table])) # async d.addCallback(make_url) d.addCallback(Reque

我想异步查询数据库中的密钥,然后为每个密钥请求几个URL

我有一个函数,它从数据库返回一个
延迟的
,该数据库的值是多个请求的键。理想情况下,我会调用此函数并返回一个从
start\u请求推迟的生成器

@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\u请求
必须返回
Request
对象,而不是值为
Request
对象的延迟。spider中间件的
进程启动请求()
似乎也是如此

或者,我可以向,比如说,
http://localhost/
并在通过downloader中间件的
process_request()
从数据库获得密钥后将其更改为真实url。但是,
process\u request
只返回一个
request
对象;它不能使用以下键向多个页面发出请求:正在尝试
yield Request(url)
raises

AssertionError: Middleware myDownloaderMiddleware.process_request
must return None, Response or Request, got generator
最干净的解决方案是什么

  • 从数据库异步获取密钥
  • 对于每个密钥,生成几个请求

您可以让延迟对象的回调将URL传递给某种类型的生成器。然后,生成器将任何接收到的URL转换为scrapy请求对象并生成它们。下面是使用链接的代码(未测试)的示例:


完成后不要忘记停止请求生成器。

您没有提供异步数据库查询的必要用例。我假设你不能开始刮你的网址,除非你先查询数据库?如果是这种情况,那么最好同步执行查询,迭代查询结果,提取所需内容,然后生成
Request
对象。异步查询数据库而只是坐在那里等待查询完成是没有意义的。

看一看,我不确定我是否理解你的意思。这段代码说,
generator对象没有属性“dont\u filter”
,这也是同样的问题--
start\u requests()
需要生成请求对象,而不是生成器。在生成器上循环也是如此:。你能澄清一下吗?我想我明白你想做什么。我已经更新了答案以澄清问题。这是一个工作队列。如果我一次得到所有的工作,第二次连接就不会剩下任何工作了。对于长期运行的刮擦,一次得到一个作业,异步,是相当有效的,我想。我不完全确定你想要传达什么。您能否提供更多的上下文来了解您的问题所在,并可能提供您尝试过的更多代码
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