2015-06-21 12 views
5

Tôi đang tổng hợp dữ liệu hàng ngày bằng Scrapy bằng cách sử dụng thu thập thông tin hai giai đoạn. Giai đoạn đầu tiên tạo ra một danh sách các URL từ một trang chỉ mục và giai đoạn thứ hai viết HTML, cho mỗi URL trong danh sách, đến một chủ đề Kafka.Phế liệu `ReactorNotRestartable`: một lớp để chạy hai (hoặc nhiều hơn) nhện

kafka cluster for Scrapy crawler

Mặc dù hai thành phần của thu thập dữ liệu có liên quan, tôi muốn họ được độc lập: các url_generator sẽ chạy như một nhiệm vụ theo lịch trình mỗi ngày một lần, và page_requester sẽ chạy liên tục, xử lý URL khi có sẵn. Vì mục đích "lịch sự", tôi sẽ điều chỉnh DOWNLOAD_DELAY để trình thu thập thông tin hoàn tất tốt trong khoảng thời gian 24 giờ, nhưng đặt tải tối thiểu trên trang web.

Tôi tạo ra một lớp CrawlerRunner có chức năng để tạo ra của URL và lấy mã HTML:

from twisted.internet import reactor 
from scrapy.crawler import Crawler 
from scrapy import log, signals 
from scrapy_somesite.spiders.create_urls_spider import CreateSomeSiteUrlList 
from scrapy_somesite.spiders.crawl_urls_spider import SomeSiteRetrievePages 
from scrapy.utils.project import get_project_settings 
import os 
import sys 

class CrawlerRunner: 

    def __init__(self): 
     sys.path.append(os.path.join(os.path.curdir, "crawl/somesite")) 
     os.environ['SCRAPY_SETTINGS_MODULE'] = 'scrapy_somesite.settings' 
     self.settings = get_project_settings() 
     log.start() 

    def create_urls(self): 
     spider = CreateSomeSiteUrlList() 
     crawler_create_urls = Crawler(self.settings) 
     crawler_create_urls.signals.connect(reactor.stop, signal=signals.spider_closed) 
     crawler_create_urls.configure() 
     crawler_create_urls.crawl(spider) 
     crawler_create_urls.start() 
     reactor.run() 

    def crawl_urls(self): 
     spider = SomeSiteRetrievePages() 
     crawler_crawl_urls = Crawler(self.settings) 
     crawler_crawl_urls.signals.connect(reactor.stop, signal=signals.spider_closed) 
     crawler_crawl_urls.configure() 
     crawler_crawl_urls.crawl(spider) 
     crawler_crawl_urls.start() 
     reactor.run() 

Khi tôi nhanh chóng lớp, tôi có thể thực hiện thành công một trong hai chức năng riêng của nó, nhưng không may, tôi không thể thực hiện chúng với nhau:

from crawl.somesite import crawler_runner 

cr = crawler_runner.CrawlerRunner() 

cr.create_urls() 
cr.crawl_urls() 

cuộc gọi chức năng thứ hai tạo ra một twisted.internet.error.ReactorNotRestartable khi nó cố gắng để thực hiện reactor.run() trong crawl_urls chức năng.

Tôi tự hỏi liệu có sửa chữa dễ dàng mã này không (ví dụ: một số cách để chạy hai lò phản ứng xoắn riêng biệt) hoặc nếu có cách nào tốt hơn để cấu trúc dự án này.

Trả lời

6

Có thể chạy nhiều nhện trong một lò phản ứng bằng cách giữ lò phản ứng mở cho đến khi tất cả các nhện ngừng hoạt động. Điều này đạt được bằng cách giữ một danh sách của tất cả các nhện chạy và không thực hiện reactor.stop() cho đến khi danh sách này là rỗng:

import sys 
import os 
from scrapy.utils.project import get_project_settings 
from scrapy_somesite.spiders.create_urls_spider import Spider1 
from scrapy_somesite.spiders.crawl_urls_spider import Spider2 

from scrapy import signals, log 
from twisted.internet import reactor 
from scrapy.crawler import Crawler 

class CrawlRunner: 

    def __init__(self): 
     self.running_crawlers = [] 

    def spider_closing(self, spider): 
     log.msg("Spider closed: %s" % spider, level=log.INFO) 
     self.running_crawlers.remove(spider) 
     if not self.running_crawlers: 
      reactor.stop() 

    def run(self): 

     sys.path.append(os.path.join(os.path.curdir, "crawl/somesite")) 
     os.environ['SCRAPY_SETTINGS_MODULE'] = 'scrapy_somesite.settings' 
     settings = get_project_settings() 
     log.start(loglevel=log.DEBUG) 

     to_crawl = [Spider1, Spider2] 

     for spider in to_crawl: 

      crawler = Crawler(settings) 
      crawler_obj = spider() 
      self.running_crawlers.append(crawler_obj) 

      crawler.signals.connect(self.spider_closing, signal=signals.spider_closed) 
      crawler.configure() 
      crawler.crawl(crawler_obj) 
      crawler.start() 

     reactor.run() 

Các lớp được thực hiện:

from crawl.somesite.crawl import CrawlRunner 

cr = CrawlRunner() 
cr.run() 

Giải pháp này được dựa trên một blogpost by Kiran Koduru.

+0

Có cách nào để thêm trình thu thập thông tin vào lò phản ứng trong khi đang chạy không? Làm thế nào điều này có thể được thực hiện reactor.run() đang chặn? –

+1

Cảm ơn tín dụng :) –

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