Điều này không dễ dàng vì Scrapy không chặn và hoạt động trong vòng lặp sự kiện; nó sử dụng vòng lặp sự kiện Xoắn và vòng lặp sự kiện Xoắn không thể khởi động lại được, vì vậy bạn không thể viết crawler.start(); data = crawler.data
- sau khi quá trình crawler.start()
chạy mãi mãi, gọi lại cuộc gọi đã đăng ký cho đến khi nó bị giết hoặc kết thúc.
Những câu trả lời có thể có liên quan:
Nếu bạn sử dụng một vòng lặp sự kiện trong ứng dụng của bạn (ví dụ như bạn có một máy chủ web Twisted hoặc Tornado) sau đó nó là có thể lấy dữ liệu từ thu thập thông tin mà không lưu trữ dữ liệu vào đĩa. Ý tưởng là để nghe tín hiệu item_scraped. Tôi đang sử dụng helper sau để làm cho nó đẹp hơn:
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()
API được lấy cảm hứng từ motor, một tài xế MongoDB cho các khuôn khổ async. Sử dụng scrape_items bạn có thể lấy các mục từ các cuộc gọi lại bị xoắn hoặc lốc xoáy ngay khi chúng được cạo, theo cách tương tự như cách bạn tìm nạp các mục từ một truy vấn MongoDB.
Nguồn
2016-11-21 08:17:25