python - scrapy django 使用抓取的数据更新数据库

标签 python django scrapy

我目前有 scrapy 蜘蛛,可以抓取 XML feed 并使用 django 模型将信息存储在 postgres 数据库中。

这一切都很完美,并且得到了我想要的确切信息。问题是数据库需要每天更新一次,添加新信息、更改信息或删除不再存在的信息。

所以基本上,当蜘蛛运行时,我希望它检查它是否已经在数据库中,如果它是完全相同的信息,则忽略它,如果信息已更改,请更改它,或者如果它不再存在,请删除它信息。

我似乎不知道如何做到这一点。任何想法将不胜感激。

布莱恩

最佳答案

可能与 How to update DjangoItem in Scrapy 重复

NT3RP 提供了一个很好的解决方案,只需一个管道和几个函数即可更新所有 django 模型。

您可以填充从对象的数据构造的“假”主键。然后您可以保存数据并在模型中更新它(如果已仅在一个管道中抓取):

class ItemPersistencePipeline(object):
    def process_item(self, item, spider):
        try:
             item_model = item_to_model(item)
        except TypeError:
            return item   
        model, created = get_or_create(item_model)
        try:
            update_model(model, item_model)
        except Exception,e:
            return e
        return item

当然是方法:

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

def get_or_create(model):
    model_class = type(model)
    created = False
    try:
        #We have no unique identifier at the moment
        #use the model.primary for now
        obj = model_class.objects.get(primary=model.primary)
    except model_class.DoesNotExist:
        created = True
        obj = model  # DjangoItem created a model for us.

    return (obj, created)

from django.forms.models import model_to_dict

def update_model(destination, source, commit=True):
    pk = destination.pk

    source_dict = model_to_dict(source)
    for (key, value) in source_dict.items():
        setattr(destination, key, value)

    setattr(destination, 'pk', pk)

    if commit:
        destination.save()

    return destination

此外,您还应该在 django 模型中定义字段“primary”,以搜索是否已在抓取的新项目中

models.py

class Parent(models.Model):
    field1 = CharField()   
    #primary_key=True
    primary = models.CharField(max_length=80)
class ParentX(models.Model):
    field2 = CharField()
    parent = models.OneToOneField(Parent, related_name = 'extra_properties')
    primary = models.CharField(max_length=80) 
class Child(models.Model):
    field3 = CharField()
    parent = models.ForeignKey(Parent, related_name='childs')
    primary = models.CharField(max_length=80)

关于python - scrapy django 使用抓取的数据更新数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16988089/

相关文章:

python - Python多处理中的字符串参数

python - 动态定义具有不同签名的函数

python - 未找到 keras 模块(没有名为 'keras' 的模块)

python - 使用 alembic.config.main 重定向日志输出

Django 按字典过滤模型

python - Django 管理 "save and view on site"按钮

django - 如何从 Django 中的 CharField 获取当前选择的选项?

python - 使用xpath获取图像

python - 如何在 Scrapy 中使用 response.XPath 从多个标签中提取文本数据?

python - 如何在 MySQL 数据库中存储动态 python 字典?