2016-11-21 6 views
5

मैं वर्तमान में एक वेब ऐप बना रहा हूं जिसका अर्थ है एक स्केपर स्पाइडर द्वारा एकत्र किए गए डेटा को प्रदर्शित करने के लिए। उपयोगकर्ता अनुरोध करता है, मकड़ी एक वेबसाइट क्रॉल करता है, फिर संकेत मिलने के लिए डेटा को ऐप पर वापस कर देता है। मैं इंटरमीडिएरी .csv या .json फ़ाइल पर भरोसा किए बिना सीधे स्क्रैपर से डेटा पुनर्प्राप्त करना चाहता हूं। कुछ ऐसा:एक स्केपर क्रॉलर से डेटा को एक चर में कैसे सहेजना है?

from scrapy.crawler import CrawlerProcess 
from scraper.spiders import MySpider 

url = 'www.example.com' 
spider = MySpider() 
crawler = CrawlerProcess() 
crawler.crawl(spider, start_urls=[url]) 
crawler.start() 
data = crawler.data # this bit 

उत्तर

6

यह इतना आसान नहीं है क्योंकि स्केपर गैर-अवरुद्ध है और एक ईवेंट लूप में काम करता है; यह ट्विस्टेड इवेंट लूप का उपयोग करता है, और ट्विस्टेड इवेंट लूप पुनरारंभ करने योग्य नहीं है, इसलिए आप crawler.start(); data = crawler.data नहीं लिख सकते हैं - crawler.start() प्रक्रिया के बाद हमेशा के लिए चलती है, जब तक कि इसे मार या समाप्त नहीं किया जाता है, तब तक पंजीकृत कॉलबैक को कॉल करना।

ये जवाब प्रासंगिक हो सकता है:

आप अपने अनुप्रयोग में एक घटना पाश का उपयोग करते हैं (उदाहरण के लिए यदि आप एक मुड़ या तूफान वेब सर्वर है) तो यह है डिस्क पर संग्रहीत किए बिना क्रॉल से डेटा प्राप्त करना संभव है। विचार आइटम_स्क्रैड सिग्नल को सुनना है। मैं इसे अच्छे बनाने के लिए निम्नलिखित सहायक उपयोग कर रहा हूँ:

import collections 

from twisted.internet.defer import Deferred 
from scrapy.crawler import Crawler 
from scrapy import signals 

def scrape_items(crawler_runner, crawler_or_spidercls, *args, **kwargs): 
    """ 
    Start a crawl and return an object (ItemCursor instance) 
    which allows to retrieve scraped items and wait for items 
    to become available. 

    Example: 

    .. code-block:: python 

     @inlineCallbacks 
     def f(): 
      runner = CrawlerRunner() 
      async_items = scrape_items(runner, my_spider) 
      while (yield async_items.fetch_next): 
       item = async_items.next_item() 
       # ... 
      # ... 

    This convoluted way to write a loop should become unnecessary 
    in Python 3.5 because of ``async for``. 
    """ 
    crawler = crawler_runner.create_crawler(crawler_or_spidercls)  
    d = crawler_runner.crawl(crawler, *args, **kwargs) 
    return ItemCursor(d, crawler) 


class ItemCursor(object): 
    def __init__(self, crawl_d, crawler): 
     self.crawl_d = crawl_d 
     self.crawler = crawler 

     crawler.signals.connect(self._on_item_scraped, signals.item_scraped) 

     crawl_d.addCallback(self._on_finished) 
     crawl_d.addErrback(self._on_error) 

     self.closed = False 
     self._items_available = Deferred() 
     self._items = collections.deque() 

    def _on_item_scraped(self, item): 
     self._items.append(item) 
     self._items_available.callback(True) 
     self._items_available = Deferred() 

    def _on_finished(self, result): 
     self.closed = True 
     self._items_available.callback(False) 

    def _on_error(self, failure): 
     self.closed = True 
     self._items_available.errback(failure) 

    @property 
    def fetch_next(self): 
     """ 
     A Deferred used with ``inlineCallbacks`` or ``gen.coroutine`` to 
     asynchronously retrieve the next item, waiting for an item to be 
     crawled if necessary. Resolves to ``False`` if the crawl is finished, 
     otherwise :meth:`next_item` is guaranteed to return an item 
     (a dict or a scrapy.Item instance). 
     """ 
     if self.closed: 
      # crawl is finished 
      d = Deferred() 
      d.callback(False) 
      return d 

     if self._items: 
      # result is ready 
      d = Deferred() 
      d.callback(True) 
      return d 

     # We're active, but item is not ready yet. Return a Deferred which 
     # resolves to True if item is scraped or to False if crawl is stopped. 
     return self._items_available 

    def next_item(self): 
     """Get a document from the most recently fetched batch, or ``None``. 
     See :attr:`fetch_next`. 
     """ 
     if not self._items: 
      return None 
     return self._items.popleft() 

एपीआई motor, async चौखटे के लिए एक MongoDB ड्राइवर से प्रेरित है। Scrape_items का उपयोग करके आप मोड़ या टर्ननाडो कॉलबैक से सामान प्राप्त कर सकते हैं जैसे ही वे स्क्रैप किए जाते हैं, वैसे ही जैसे आप मोंगोडीबी क्वेरी से आइटम कैसे प्राप्त करते हैं।

संबंधित मुद्दे