Python 用于在多个请求中使用的密钥的异步查询数据库
我想异步查询数据库中的密钥,然后为每个密钥请求几个URL 我有一个函数,它从数据库返回一个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
延迟的,该数据库的值是多个请求的键。理想情况下,我会调用此函数并返回一个从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