Scrapy / Django - 与DjangoItem的外键关系

时间:2015-02-21 20:30:09

标签: django-models scrapy-spider

以下是我在Scrapy蜘蛛中所拥有的内容:

phone_model = SmartphoneItem()
phone_model['sku_number'] = sku_number

# code omitted

cellular_network = CellularNetworkItem()
cellular_network['phone_model'] = phone_model
cellular_network['speed'] = speed
...

在models.py中:

class CellularNetwork(models.Model): 
    phone_model = models.ForeignKey('Smartphone', unique=True)
    ...

class Smartphone(models.Model):
    sku_number = models.IntegerField(max_length=40, primary_key=True)
    ....

和items.py:

class CellularNetworkItem(DjangoItem):
    django_model = CellularNetwork

class SmartphoneItem(DjangoItem):
    django_model = Smartphone

但是,分配phone_model = SmartphoneItem()显然不会产生智能手机模型。

我正在抓取一堆规范,并希望在源头验证数据。由于无论如何都必须对数据进行标准化以进行验证,我更喜欢一石一鸟地杀死它并立即更新数据库。

看起来ORM与简单的Scrapy项目之间的关系能力就是销售DjangoItem的能力。但我似乎无法找到任何直接在蜘蛛中利用此功能的示例。我似乎有些人使用管道,逐个处理isinstance模式匹配的对象......我开始怀疑我是否可以将Django模型直接导入到蜘蛛。

更新:已解决。

基于How to update DjangoItem in Scrapy,我把它放在蜘蛛中直接返回Django模型实例:

def item_to_model(self, item):
    model_class = getattr(item, 'django_model')
    if not model_class:
        raise TypeError("Item is not a `DjangoItem` or is misconfigured")

    return item.instance

更新2:仍然破碎:

说得太快了。虽然这提供了一个有效的Django实例,但它不是 实例。这是djangoitem.py的相关部分:

@property
def instance(self):
    if self._instance is None:
        modelargs = dict((k, self.get(k)) for k in self._values
                          if k in self._model_fields)
        self._instance = self.django_model(**modelargs)
    return self._instance

我不完全理解发生了什么,但我收集它给了我们一个新的实例。

1 个答案:

答案 0 :(得分:0)

问题看起来很旧,但无论如何。首先,你错过了一条将通过"传递的管道。 Django的项目。 Second,对于FK,您需要 Django对象(正确的模型)的实例,而不是 Scrapy项目的实例。所以你的代码应该看起来像这样:

class SmartphonePipeline(object):

    def process_item(self, item, spider):
        sku_number = item['sku_number']
        smartphone, created = Smartphone.objects.get_or_create(sku_number=item['sku_number'])
        if created:
            smartphone.save()

class CellularNetworkPipeline(object):

    def process_item(self, item, spider):
        smartphone_item = item['phone_model']
        smartphone = Smartphone.objects.get(sku_number=smartphone_item["sku_number"])
        cellular_network, created = CellularNetwork.objects.get_or_create(phone_model=smartphone)
        cellular_network.speed = item['speed']
        cellular_network.save()
        return item