Мне удалось реализовать нечто подобное в одном из моих проектов. Это мини-проект, и я искал быстрое решение. Вам может понадобиться изменить его или поддерживать многопоточность и т. Д., Если вы поместите его в производственную среду.
Обзор
Я создал ItemPipeline
, который просто добавляет элементы в InMemoryItemStore
помощник. Затем в моем коде __main__
я жду, пока сканер завершит работу, и вытащу все элементы из InMemoryItemStore
. Тогда я могу манипулировать предметами так, как мне хочется.
код
items_store.py
Хакерский магазин в памяти. Это не очень элегантно, но это сделало работу за меня. Изменить и улучшить, если хотите. Я реализовал это как простой объект класса, чтобы я мог просто импортировать его в любое место проекта и использовать его, не передавая его экземпляр.
class InMemoryItemStore(object):
__ITEM_STORE = None
@classmethod
def pop_items(cls):
items = cls.__ITEM_STORE or []
cls.__ITEM_STORE = None
return items
@classmethod
def add_item(cls, item):
if not cls.__ITEM_STORE:
cls.__ITEM_STORE = []
cls.__ITEM_STORE.append(item)
pipelines.py
Этот пиплайн будет хранить объекты в хранилище в памяти из фрагмента выше. Все элементы просто возвращаются, чтобы сохранить нормальный поток в трубопроводе. Если вы не хотите передавать некоторые элементы в другие конвейеры, просто измените process_item
, чтобы не возвращать все элементы.
from <your-project>.items_store import InMemoryItemStore
class StoreInMemoryPipeline(object):
"""Add items to the in-memory item store."""
def process_item(self, item, spider):
InMemoryItemStore.add_item(item)
return item
settings.py
Теперь добавьте StoreInMemoryPipeline
в настройках скребка. Если вы измените метод process_item
, описанный выше, убедитесь, что вы установили правильный приоритет здесь (изменив значение 100 здесь).
ITEM_PIPELINES = {
...
'<your-project-name>.pipelines.StoreInMemoryPipeline': 100,
...
}
main.py
Здесь я связываю все эти вещи вместе. Я очищаю хранилище в памяти, запускаю сканер и выбираю все элементы.
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
from <your-project>.items_store import InMemoryItemStore
from <your-project>.spiders.your_spider import YourSpider
def get_crawler_items(**kwargs):
InMemoryItemStore.pop_items()
process = CrawlerProcess(get_project_settings())
process.crawl(YourSpider, **kwargs)
process.start() # the script will block here until the crawling is finished
process.stop()
return InMemoryItemStore.pop_items()
if __name__ == "__main__":
items = get_crawler_items()