在Scrapy爬虫中是否可以使用多线程?比如说我已经创建了一个爬虫,它会爬取博客主题并保存其中所有的信息。我想让每个主题都与一个线程从池子里绑定,这个线程将爬取所有需要的信息。这样每个线程就可以爬取不同的主题了。
这个标记的答案并不是100%正确。
Scrapy运行在Twisted上,支持从pipeline的 process_item
方法中返回deferreds。
这意味着您可以在管道中创建一个deferred,例如使用threads.deferToThread
。 这将在反应器线程池中运行您的CPU绑定代码。请注意,在适当的位置使用callFromThread
。 我使用信号量来避免耗尽线程池中的所有线程,但为下面提到的设置设置良好的值也可能起作用。
http://twistedmatrix.com/documents/13.2.0/core/howto/threading.html
这里是我其中一个项目管道的方法:
def process_item(self, item, spider):
def handle_error(item):
raise DropItem("error processing %s", item)
d = self.sem.run(threads.deferToThread, self.do_cpu_intense_work, item)
d.addCallback(lambda _: item)
d.addErrback(lambda _: handle_error(item))
return d
你可能希望关注 REACTOR_THREADPOOL_MAXSIZE
,如此处所述: http://doc.scrapy.org/en/latest/topics/settings.html#reactor-threadpool-maxsize
以及 CONCURRENT_ITEMS
,如此处所述: http://doc.scrapy.org/en/latest/topics/settings.html#concurrent-items
然而,你仍会面临Python GIL的问题,这意味着CPU密集型任务实际上不会在多个CPU上并行运行,它们只是假装在那样做。GIL仅针对IO释放。但你可以使用此方法在项目管道中使用IO阻塞的第三方库(例如webservice调用),而不会阻塞反应器线程。
DeferredSemaphore
来“限制”Twisted线程池中的工作量?难道不是Scrapy的CONCURRENT_ITEMS
设置来处理它吗? - abhinavkulkarniDeferredSemaphore
时,您如何跟踪Scrapy中使用的总资源?您会保留一个全局的吗?每个项目管道一个?还是每个爬虫一个? - abhinavkulkarni