2011-11-03 52 views
10

當我從命令行'一次性'場景運行它時,我的Scrapy腳本似乎工作得很好,但是如果我嘗試在同一個python會話中運行兩次代碼,則會出現此錯誤:在Python中運行Scrapy任務

「ReactorNotRestartable」

爲什麼?

有問題的代碼(最後一行拋出錯誤):

crawler = CrawlerProcess(settings) 
crawler.install() 
crawler.configure() 

# schedule spider 
#crawler.crawl(MySpider()) 
spider = MySpider() 
crawler.queue.append_spider(spider) 

# start engine scrapy/twisted 
crawler.start() 

回答

11

接近喬爾的答案,但我想在評論中詳細闡述一下。如果您查看Crawler source code,您會看到CrawlerProcess類有start,但也有stop函數。這stop函數負責清理爬行的內部,以便系統在可以重新啓動的狀態下結束。

因此,如果您想要在不離開過程的情況下重新開始爬網,請在適當的時間撥打crawler.stop()。稍後,再次致電crawler.start()即可恢復運營。

編輯:回想起來,這是不可能的(由於Twisted反應器,在不同的答案中提到); stop只是照顧一個乾淨的終止。回顧我的代碼,我碰巧有一個Crawler進程的包裝器。在下面你可以找到一些(編輯過的)代碼,使它能夠使用Python的多處理模塊工作。通過這種方式可以更輕鬆地重新啓動抓取工具。 (注:我上個月發現的代碼在網上,但我並沒有包括源...因此,如果有人知道它是從哪裏來的,我會更新的學分源)

from scrapy import project, signals 
from scrapy.conf import settings 
from scrapy.crawler import CrawlerProcess 
from scrapy.xlib.pydispatch import dispatcher 
from multiprocessing.queues import Queue 
from multiprocessing import Process 

class CrawlerWorker(Process): 
    def __init__(self, spider, results): 
     Process.__init__(self) 
     self.results = results 

     self.crawler = CrawlerProcess(settings) 
     if not hasattr(project, 'crawler'): 
      self.crawler.install() 
     self.crawler.configure() 

     self.items = [] 
     self.spider = spider 
     dispatcher.connect(self._item_passed, signals.item_passed) 

    def _item_passed(self, item): 
     self.items.append(item) 

    def run(self): 
     self.crawler.crawl(self.spider) 
     self.crawler.start() 
     self.crawler.stop() 
     self.results.put(self.items) 

# The part below can be called as often as you want 
results = Queue() 
crawler = CrawlerWorker(MySpider(myArgs), results) 
crawler.start() 
for item in results.get(): 
    pass # Do something with item 
+0

加入crawler.start後立即crawler.stop()()沒有幫助 - 怎麼辦我發現「適當的時間」? – Trindaz

+0

@Trindaz:我在那次電話會議上不正確,請查看最新的答案。 – jro

+0

感謝您的更新@jro。我之前也看過這個片段,如果我已經正確地解釋了這一點,那麼這個概念就可以通過將蜘蛛添加到永不死亡的爬蟲來抓取儘可能多的概念,而不是每次嘗試重新啓動爬蟲。你在「執行」一個蜘蛛。我將其標記爲解決方案,因爲從技術上講,它解決了我的問題,但對我來說是不可用的,因爲我不想依賴於我正在使用它的django應用程序中的持久性搜尋器對象。我最終編寫了一個基於純粹在BeautifulSoup和urllib2上。 – Trindaz

-1

在我看來,你不能使用crawler.start()命令兩次:您可能需要重新創建它,如果你想讓它運行第二次。

2

crawler.start()啓動扭曲的反應堆。只能有一個反應堆。

如果你想運行更蜘蛛 - 使用

another_spider = MyAnotherSpider() 
crawler.queue.append_spider(another_spider) 
+0

scrapy 0.14不再支持爬蟲程序中的多個蜘蛛。 – goh

+0

還沒有測試過,但是這可能起作用(查看源代碼):'crawler.engine.open_spider(another_spider)' – warvariuc

+0

剛剛嘗試過您的建議。嗯,我無法阻止這個過程... – goh

0

我使用的線程在一個應用程序啓動器的幾個時間,避免ReactorNotRestartable錯誤。

線程(目標=的Process.Start)。開始()

下面是詳細的解釋:Run a Scrapy spider in a Celery Task