2011-11-03 25 views
10

Kịch bản lệnh Scrapy của tôi dường như hoạt động tốt khi tôi chạy nó trong kịch bản 'một lần' từ dòng lệnh, nhưng nếu tôi thử chạy mã hai lần trong cùng phiên python, tôi nhận được lỗi này:Chạy các tác vụ Phế liệu trong Python

"ReactorNotRestartable"

Tại sao?

Các mã vi phạm (dòng cuối cùng ném lỗi):

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() 

Trả lời

11

Đóng câu trả lời của Joël, nhưng tôi muốn xây dựng nhiều hơn một chút so với ý kiến ​​có thể. Nếu bạn nhìn vào số Crawler source code, bạn thấy rằng lớp CrawlerProcess có một số start, nhưng cũng có chức năng stop. Chức năng này stop sẽ chăm sóc làm sạch nội bộ của thu thập thông tin để hệ thống kết thúc ở trạng thái mà từ đó nó có thể bắt đầu lại.

Vì vậy, nếu bạn muốn khởi động lại thu thập dữ liệu mà không cần thoát khỏi quá trình của mình, hãy gọi crawler.stop() vào thời điểm thích hợp. Sau đó, chỉ cần gọi lại crawler.start() để tiếp tục hoạt động.

Chỉnh sửa: nhìn lại, điều này là không thể (do lò phản ứng xoắn, như được đề cập trong một câu trả lời khác); các stop chỉ cần chăm sóc của một chấm dứt sạch sẽ. Nhìn lại mã của tôi, tôi tình cờ có một trình bao bọc cho các quy trình Trình thu thập thông tin. Dưới đây bạn có thể tìm thấy một số (redacted) mã để làm cho nó hoạt động bằng cách sử dụng mô-đun đa xử lý của Python. Bằng cách này, bạn có thể dễ dàng khởi động lại trình thu thập thông tin. (Lưu ý:. Tôi tìm thấy mã trực tuyến vào tháng trước, nhưng tôi đã không bao gồm các nguồn ... vì vậy nếu ai đó biết nó đến từ đâu, tôi sẽ cập nhật các khoản tín dụng cho các nguồn)

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

thêm crawler.stop() ngay sau khi crawler.start() đã không giúp đỡ - làm thế nào để Tôi phát hiện ra "thời gian thích hợp"? – Trindaz

+0

@Trindaz: Tôi không chính xác về cuộc gọi đó, vui lòng xem câu trả lời được cập nhật. – jro

+0

Cảm ơn bạn đã cập nhật @jro. Tôi đã nhìn thấy đoạn mã này trước và nếu tôi đã giải thích chính xác, thì khái niệm là bạn có thể cạo bao nhiêu tùy ý bằng cách thêm nhện vào trình thu thập thông tin không bao giờ chết, thay vì cố gắng khởi động lại trình thu thập thông tin cho mọi nỗ lực bạn thực hiện tại "thực hiện" một con nhện. Tôi đã đánh dấu đây là giải pháp vì kỹ thuật giải quyết vấn đề của tôi nhưng không thể sử dụng được vì tôi không muốn dựa vào các đối tượng trình thu thập dữ liệu liên tục trong ứng dụng django mà tôi đang sử dụng. Tôi đã viết một giải pháp hoàn toàn dựa trên trên BeautifulSoup và urllib2. – Trindaz

-1

Dường như với tôi rằng bạn không thể sử dụng crawler.start() lệnh hai lần: bạn có thể phải tái tạo nó nếu bạn muốn nó chạy lần thứ hai .

2

crawler.start() bắt đầu lò phản ứng xoắn. Chỉ có thể có một lò phản ứng.

Nếu bạn muốn chạy nhiều nhện - sử dụng

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

scrapy 0.14 không hỗ trợ nhiều trình thu thập thông tin trong quy trình thu thập dữ liệu nữa. – goh

+0

chưa được thử nghiệm, nhưng điều này có thể hoạt động (từ việc xem mã nguồn): 'crawler.engine.open_spider (another_spider)' – warvariuc

+0

vừa thử các đề xuất của bạn. Hmm Tôi không thể dừng quá trình ... – goh

0

Tôi đã sử dụng chủ đề để bắt đầu lò phản ứng nhiều thời gian trong một ứng dụng và tránh lỗi ReactorNotRestartable.

Thread (target = Process.Start) .start()

Dưới đây là giải thích chi tiết: Run a Scrapy spider in a Celery Task

Các vấn đề liên quan