【问题标题】:Get scrapy result inside a Django view在Django视图中获取scrapy结果
【发布时间】:2019-02-08 00:53:46
【问题描述】:

我正在成功地报废一个页面,该页面返回给我一个独特的项目。我既不想将报废的项目保存在数据库中,也不想保存到文件中。我需要在 Django 视图中获取它。

我的看法如下:

def start_crawl(process_number, court):
    """
    Starts the crawler.

        Args:
            process_number (str): Process number to be found.
            court (str): Court of the process.
    """
    runner = CrawlerRunner(get_project_settings())
    results = list()

    def crawler_results(sender, parse_result, **kwargs):
        results.append(parse_result)

    dispatcher.connect(crawler_results, signal=signals.item_passed)
    process_info = runner.crawl(MySpider, process_number=process_number, court=court)

    return results

我关注了this 解决方案,但结果列表始终为空。

我读到的内容是创建自定义中间件并在 process_spider_output 方法中获取结果。

我怎样才能得到想要的结果?

谢谢!

【问题讨论】:

  • 有时你需要做一个额外的步骤来达到你的目标。我认为分而治之更容易。使用 scrapy 将数据存储到数据库中。使用 django 从数据库中提取数据并在视图中显示。
  • @ThomasSrub 这里的问题是很难确定蜘蛛完成后数据何时已经在数据库中以及何时报废。

标签: django scrapy


【解决方案1】:

我设法在我的一个项目中实现了类似的东西。这是一个小型项目,我正在寻找一个快速的解决方案。如果您将其置于生产环境中,您可能需要对其进行修改或支持多线程等。

概述

我创建了一个 ItemPipeline,它只是将项目添加到 InMemoryItemStore 助手中。然后,在我的__main__ 代码中,我等待爬虫完成,然后将所有项目从InMemoryItemStore 中弹出。然后我就可以随心所欲地操作这些项目了。

代码

items_store.py

​​>

Hacky 内存存储。它不是很优雅,但它为我完成了工作。如果您愿意,可以修改和改进。我已经将它实现为一个简单的类对象,因此我可以简单地将它导入项目中的任何位置并使用它,而无需传递它的实例。

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)

管道.py

​​>

此管道将从上面的 sn-p 将对象存储在内存存储中。所有项目都简单地返回以保持常规管道流完好无损。如果您不想将某些项目向下传递到其他管道,只需更改 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()

【讨论】:

  • 感谢@Almong Cohen!我从一个线程中得到了一个信号错误,最终用 scrapyrt 得到了想要的结果
【解决方案2】:

如果您真的想在“特殊”对象中收集所有数据。 将数据存储在单独的管道中,例如https://doc.scrapy.org/en/latest/topics/item-pipeline.html#duplicates-filter,然后在 close_spider (https://doc.scrapy.org/en/latest/topics/item-pipeline.html?highlight=close_spider#close_spider) 中打开 django 对象。

【讨论】:

  • 谢谢。我访问了您传递的链接,但我不知道如何避免将收集的项目保存在数据库中
  • 将它们存储在 python 对象中,并在 close_spider 中将它们传递给 django 视图
猜你喜欢
  • 2022-07-05
  • 2018-08-04
  • 2015-01-13
  • 1970-01-01
  • 1970-01-01
  • 2017-07-28
  • 1970-01-01
  • 1970-01-01
  • 2011-03-23
相关资源
最近更新 更多