【问题标题】:python django scrapy return item to controllerpython django scrapy将项目返回给控制器
【发布时间】:2016-12-30 03:55:29
【问题描述】:

我需要做一些简短的实时抓取并在我的 Django REST 控制器中返回结果数据。

尝试使用scrapy:

import scrapy
from scrapy.selector import Selector

from . models import Product

class MysiteSpider(scrapy.Spider):
    name = "quotes"
    start_urls = [
        'https://www.something.com/browse?q=dfd',
    ]
    allowed_domains = ['something.com']

    def parse(self, response):
        items_list = Selector(response).xpath('//li[@itemprop="itemListElement"]')

        for value in items_list:
            item = Product()
            item['picture_url'] = value.xpath('img/@src').extract()[0]
            item['title'] = value.xpath('h2').text()
            item['price'] = value.xpath('p[contains(@class, "ad-price")]').text()
            yield item

物品模型

import scrapy


class Product(scrapy.Item):
    name = scrapy.Field()
    price = scrapy.Field()
    picture_url = scrapy.Field()
    published_date = scrapy.Field(serializer=str)

根据 Scrapy 架构,项目将返回到 Item Pipeline (https://doc.scrapy.org/en/1.2/topics/item-pipeline.html),用于将数据存储到数据库/保存到文件等。

但是我一直被这个问题困扰 - 如何通过 Django REST APIview 返回抓取的项目列表?

预期用法示例:

from rest_framework.views import APIView
from rest_framework.response import Response

from .service.mysite_spider import MysiteSpider

    class AggregatorView(APIView):
        mysite_spider = MysiteSpider()

        def get(self, request, *args, **kwargs):

            self.mysite_spider.parse()

            return Response('good')

【问题讨论】:

  • Django REST API view 的数据应该来自http请求,而不是直接来自scrapy,所以你应该把scrapy item保存到db或者file,django可以从when读取请求即将到来。
  • 为什么它必须来自request?为什么我不能在控制器中使用一些逻辑?我现在更新了主题以表明我的意思。

标签: python django python-3.x scrapy


【解决方案1】:

我实际上并没有测试与 Django REST 框架的集成,但是下面的 sn-p 将允许您从 python 脚本运行 Spider,收集生成的项目以供以后处理。

from scrapy import signals
from scrapy.crawler import Crawler, CrawlerProcess
from ... import MysiteSpider

items = []
def collect_items(item, response, spider):
    items.append(item)

crawler = Crawler(MysiteSpider)
crawler.signals.connect(collect_items, signals.item_scraped)

process = CrawlerProcess()
process.crawl(crawler)
process.start()  # the script will block here until the crawling is finished

# at this point, the "items" variable holds the scraped items 

为了记录,这是可行的,但可能有更好的方法来做到这一点:-)

进一步阅读:

【讨论】:

  • 很好的答案,谢谢。但是当我尝试这样的事情时,出现以下错误: ValueError: signal only works in main thread
猜你喜欢
  • 1970-01-01
  • 2020-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-06
  • 1970-01-01
相关资源
最近更新 更多