Scrapy具有Item Pipelines的概念,即concurrently process(通过扭曲)从Scrapy Spider返回。以下代码示例为filtering duplicate items提供(下面复制的代码)。并发调用set
可以安全地使用process_item
吗?似乎Scrapy调用了项目管道here。
from scrapy.exceptions import DropItem
class DuplicatesPipeline:
def __init__(self):
self.ids_seen = set()
def process_item(self, item, spider):
if item['id'] in self.ids_seen:
raise DropItem("Duplicate item found: %s" % item)
else:
self.ids_seen.add(item['id'])
return item
Twisted和Scrapy主要是单线程的。它们不是抢占式多线程,而是通过协作式多任务提供并发性。在协作式多任务系统中,没有抢占。这意味着上面的process_item
之类的函数可以非常安全地假定self.ids_seen
在第一行和第二行至最后一行之间都不会改变。仅此process_item
方法正在运行。直到process_item
协作放弃控制,之后才能进行其他工作。它通过引发异常或返回值来实现。发生这种情况时,控件将返回到其调用方(或最接近的except
处理程序)。然后,该代码开始运行,直到决定放弃控制,依此类推。最终,控制权一路返回给Twisted reactor
,后者通过调用某些应用程序方法来选择另一个要服务的事件。然后重复该过程。