以下是我在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
我不完全理解发生了什么,但我收集它给了我们一个新的实例。
答案 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