优化 Django 模型设计:解决重复爬虫任务和商品数据

在开发数据采集(爬虫)应用时,我们常常面临这样一个问题:不同用户提交了相同的采集任务。为了避免在数据库中存储重复的 URL 和商品数据,我们需要优化模型设计。本文将介绍如何设计 Django 模型,以解决这个问题,并确保数据的一致性和完整性。

问题背景

假设我们有一个爬虫任务应用,用户可以提交 URL 进行数据采集。每个 URL 可能会关联多个商品数据,不同用户可能提交相同的 URL 进行采集。我们希望在数据库中只存储一个 URL,但要能映射到提交该任务的所有用户,并且每个 URL 下会有多个商品数据。此外,不同的 URL 可能会采集到相同的商品数据,因此商品数据也需要去重。

目标

  • 确保数据库中只存储唯一的采集 URL。
  • 能够映射到提交该 URL 采集任务的所有用户。
  • 确保数据库中只存储唯一的商品数据。
  • 商品数据能够映射到与其关联的多个 URL。

模型设计

以下是优化后的 Django 模型设计,通过合理的表结构和关系,解决上述问题。

1. 起始 URL 表(StartUrl)

用于存储唯一的采集 URL。

from django.db import modelsclass StartUrl(models.Model):"""起始URL表"""url = models.URLField(verbose_name="起始url", max_length=500, unique=True)class Meta:verbose_name = verbose_name_plural = '起始URL'def __str__(self):return self.url

2. 商品表(Product)

用于存储唯一的商品信息。

class Product(models.Model):"""商品表"""product_id = models.CharField(max_length=30, verbose_name='商品id', unique=True)title = models.CharField(max_length=500, verbose_name='商品标题')price = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True, verbose_name='价格')sales = models.PositiveIntegerField(blank=True, null=True, verbose_name='销量')rating = models.FloatField(blank=True, null=True, verbose_name='评分')rating_count = models.PositiveIntegerField(blank=True, null=True, verbose_name='评分数')listing_date = models.DateField(blank=True, null=True, verbose_name='上架时间')release_date = models.DateField(blank=True, null=True, verbose_name='发售时间')brand = models.CharField(blank=True, null=True, max_length=100, verbose_name='品牌')platform = models.IntegerField(verbose_name='平台')seller = models.CharField(blank=True, null=True, max_length=100, verbose_name='卖家')img_url = models.URLField(blank=True, null=True, verbose_name='商品主图地址')product_details_url = models.URLField(max_length=500, blank=True, null=True, verbose_name='商品详情地址')spider_date = models.DateTimeField(blank=True, null=True, verbose_name='完成采集时间')class Meta:verbose_name = verbose_name_plural = '商品'def __str__(self):return self.title

3. 爬虫任务表(SpiderTask)

用于关联用户和起始 URL,同时通过多对多关系关联商品。

from django.utils import timezone
from myapp.models.model_account import Userclass SpiderTask(models.Model):"""爬虫任务表"""PLATFORM_CHOICES = ((1, 'Amazon'),(2, 'Etsy'),(3, 'Temu'),(4, 'WalMart'))STATUS_CHOICES = ((0, '进行中'),(1, '已完成'),(2, '异常'),)TYPE_CHOICES = ((1, '列表页'),(2, '详情页'),)id = models.AutoField(primary_key=True, verbose_name='自增id')user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='用户')start_url = models.ForeignKey(StartUrl, on_delete=models.CASCADE, verbose_name='起始url')platform = models.IntegerField(default=1, choices=PLATFORM_CHOICES, verbose_name='平台')name = models.CharField(verbose_name="爬虫名称", max_length=255)spider_type = models.IntegerField(choices=TYPE_CHOICES, default=1, verbose_name='采集页面类型')description = models.TextField(verbose_name="描述备注等", max_length=500, null=True, blank=True)completed = models.IntegerField(choices=STATUS_CHOICES, default=0, verbose_name='完成状态')created_at = models.DateTimeField(default=timezone.now, verbose_name='加入任务时间')collection_status = models.IntegerField(choices=STATUS_CHOICES, default=0, verbose_name='采集状态')completed_at = models.DateTimeField(null=True, blank=True, verbose_name='完成时间')products = models.ManyToManyField(Product, verbose_name='关联商品', related_name='tasks')class Meta:verbose_name = verbose_name_plural = '爬虫任务'unique_together = [['user', 'start_url']]def __str__(self):return f"{self.get_platform_display()} - {self.name}"

4. 用户收藏表(SpiderUserFavorite)

用于记录用户收藏的商品信息。

class SpiderUserFavorite(models.Model):"""用户收藏表"""user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='用户')product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name='收藏商品')added_at = models.DateTimeField(default=timezone.now, verbose_name='收藏时间')note = models.TextField(blank=True, null=True, verbose_name='备注信息')tags = models.CharField(max_length=500, blank=True, null=True, verbose_name='备注标签')class Meta:verbose_name = verbose_name_plural = '用户收藏'unique_together = [['user', 'product']]def __str__(self):return f"{self.user.username} - {self.product.title}"

模型关系图

为了更清晰地展示模型之间的关系,我们绘制了以下关系图:

用户(User)
│
└──< 拥有多个│
爬虫任务(SpiderTask) >─── 属于 ────> 起始URL(StartUrl)
│           (多对一)          (一对多)
│
└───< 多对多 >───│商品(Product)

总结

通过这种优化的模型设计,我们解决了以下问题:

  • 避免重复存储 URLStartUrl 表存储唯一的采集 URL。
  • 用户与 URL 的映射:每个爬虫任务(SpiderTask)关联一个用户和一个 URL。
  • 避免重复存储商品数据Product 表存储唯一的商品数据。
  • 商品与任务的映射:通过多对多关系,商品可以映射到多个任务。

这种设计不仅提高了数据的存储效率,还确保了数据的一致性和完整性。希望这篇博客能对你在 Django 模型设计中遇到的类似问题有所帮助。

不足之处

尽管这种设计已经尽量优化了数据存储和关系映射,但在高并发的情况下,可能会遇到数据竞争的问题。例如,在多用户同时提交相同 URL 的情况下,可能会出现重复记录的风险。为了解决这个问题,可能需要进一步引入锁机制或其他并发控制策略。

作者:pycode
链接:https://juejin.cn/post/7371777383589068863

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/24455.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java生成枚举类下拉框 - 供前端使用

生成枚举类代码 1. 创建通用model枚举类封装对象 package com.ruoyi.coordination.enums;import java.io.Serializable;public class SelectBean implements Serializable {private String seKey;private String seValue;public String getSeKey() {return seKey;}public voi…

食品元宇宙 - 重新定义食品产业的未来

在数字化和创新技术的驱动下&#xff0c;我们的生活方式正在发生翻天覆地的变化。"食品元宇宙"作为这一变革浪潮中的新星&#xff0c;旨在利用虚拟现实、增强现实以及数字孪生等技术&#xff0c;彻底改变我们对于食品产业的认知和体验。从农业生产到食品加工&#xf…

第49集《摄大乘论》

《摄大乘论》&#xff0c;和尚尼慈悲、诸位法师、诸位居士&#xff0c;阿弥陀佛&#xff01;(阿弥陀佛&#xff01;)请大家打开《讲义》第一六一页&#xff0c;乙五、彼修差别分。 这一科是正宗分的第五科彼修差别分。我们在讲这一科的内容之前&#xff0c;我们先把这一科的大…

C语言小例程10/100

题目&#xff1a;要求输出国际象棋棋盘。 程序分析&#xff1a;国际象棋棋盘由64个黑白相间的格子组成&#xff0c;分为8行*8列。用i控制行&#xff0c;j来控制列&#xff0c;根据ij的和的变化来控制输出黑方格&#xff0c;还是白方格。 #include<stdio.h>int main() {…

SAP 服务提供者 (Services Provider)接口测试笔记

文章目录 SAP 服务提供者 &#xff08;Services Provider&#xff09;接口测试笔记设置Content-Type授权SAP接口测试-SoapUI参数配置 SAP 服务提供者 &#xff08;Services Provider&#xff09;接口测试笔记 现在我在SAP里面公布了一些查询接口&#xff0c;现在就是要用SoapU…

MySQL之查询性能优化(十一)

查询性能优化 查询优化器的提示(hint) 如果对优化器选择的执行计划不满意&#xff0c;可以使用优化器提供的几个提示(hint)来控制最终的执行计划。下面将列举一些常见的提示&#xff0c;并简单地给出什么时候使用该提示。通过在查询中加入相应的提示&#xff0c;就可以抗旨该…

【AIGC+CAD】革新建筑、室内设计与建模领域的GenAI产品

一、产品定位 Augrade,一款专为建筑、室内设计和建模行业打造的AI CAD自动化工具。它凭借先进的AI技术,将2D蓝图迅速转化为精确的3D CAD模型,同时提供设计、成本分析的自动化以及全面的文档生成服务。Augrade致力于简化设计流程,确保技术可行性,并促进跨团队、跨工具的协…

Java Web学习笔记19——Ajax介绍

Ajax: 概念&#xff1a;Asynchronous JavaScript And XML 异步的JavaScript和XML。 作用&#xff1a; 1&#xff09;数据交换&#xff1a;通过Ajax可以给服务器发送请求&#xff0c;并获得服务器的响应数据。 2&#xff09;异步交互&#xff1a;可以在不重新加载页面的情况…

Hadoop+Spark大数据技术 实验11 Spark 图

17周期末考试 重点从第五章 scala语言开始 比如&#xff1a;映射&#xff08;匿名函数&#xff09; 11.3.1创建属性图 import org.apache.spark.graphx._ import org.apache.spark.rdd.RDD //创建一个顶点集的RDD val users: RDD[(VertexId ,(String,String))] sc.paralle…

基于思通数科大模型的设备隐患智能检测:图像处理与声音分析的融合应用

在现代工业生产中&#xff0c;设备的稳定运行对保障生产效率和产品质量至关重要。然而&#xff0c;设备的老化、磨损以及异常状态的检测往往需要大量的人力和物力。思通数科大模型结合图像处理技术和声音分析技术&#xff0c;为设备隐患检测提供了一种自动化、高效的解决方案。…

一个训练好的神经网络的模型文件的内容主要是什么信息呢?请用大白话举例说明( 百度 API 回答 )

训练好的神经网络的模型文件&#xff0c;其实保存了神经网络学习到的“知识”和“经验”。用大白话来说&#xff0c;它主要保存了以下几类信息&#xff1a; 网络结构&#xff1a;这就像是神经网络的“骨架”或者“蓝图”&#xff0c;告诉计算机这个神经网络有哪些层&#xff0…

Docker 管理 | 代理配置、内网共享和 Harbor 部署

唠唠闲话 在现代软件开发和运维中&#xff0c;容器技术已经成为构建、部署和管理应用程序的标准工具。然而&#xff0c;在实际操作中&#xff0c;我们常常需要面对一些常见的挑战&#xff0c;如容器访问外部资源的代理配置、内网环境下的镜像共享以及企业级镜像管理。 本教程…

websocket 前端项目js示例

websocket前端 和服务端websocket通信示例&#xff0c; 前端直接使用h5的内置对象 WebSocket 来创建和管理 WebSocket 连接&#xff0c;以及可以通过该连接发送和接收数据。 这个对象都是是事件方式来处理和与后端交互数据&#xff0c; 他们分别是 onopen打开, onclose关闭, o…

关键字、保留字、标识符

关键字 关键字是被 Java 赋予了特定含义的英文单词。 关键字的字母全部小写。 保留字 现有的 Java 版本尚未使用&#xff0c;但是以后版本可能会作为关键字使用。自己命名标识符时需要避免使用这些保留字。 保留字有&#xff1a;byValue, cast, future, generic, inner, op…

Spring Boot整合WebSocket和Redis实现直播间在线人数统计功能

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

高精度加法的实现

这是C算法基础-基础算法专栏的第七篇文章&#xff0c;专栏详情请见此处。 引入 在C语言中&#xff0c;int的可存储数据范围是-2147483648~2147483647&#xff0c;long long的可存储数据范围是-9223372036854775808~9223372036854775807&#xff0c;但是如果一些数据比long long…

【TensorFlow深度学习】实现Actor-Critic算法的关键步骤

实现Actor-Critic算法的关键步骤 实现Actor-Critic算法的关键步骤&#xff1a;强化学习中的双剑合璧Actor-Critic算法简介关键实现步骤代码示例&#xff08;使用TensorFlow&#xff09;结语 实现Actor-Critic算法的关键步骤&#xff1a;强化学习中的双剑合璧 在强化学习的广阔…

Qt下调用Snap7库与西门子PLC通信

文章目录 前言一、Snap7源码下载二、Snap7的dll常用函数功能介绍三、Snap7Lib.pri模块的封装四、下载链接总结 前言 本文主要讲述了在Qt下调用Snap7库与西门子PLC进行通信&#xff0c;在这里将Snap7的源码与动态库整合在一起封装了一个自己的Snap7Lib.pri子模块&#xff0c;方…

java-集合的使用 1

Java 中的集合框架&#xff08;Collection Framework&#xff09;是 Java API 的一部分&#xff0c;提供了对各种集合数据结构的支持。集合框架使得 Java 程序员能够方便地处理集合数据&#xff0c;而不必担心底层的实现细节。Java 集合框架包括一系列接口和类&#xff0c;用于…

【Python】读取文件夹中所有excel文件拼接成一个excel表格 的方法

我们平常会遇到下载了一些Excel文件放在一个文件夹下&#xff0c;而这些Excel文件的格式都一样&#xff0c;这时候需要批量这些文件合并成一个excel 文件里。 在Python中&#xff0c;我们可以使用pandas库来读取文件夹中的所有Excel文件&#xff0c;并将它们拼接成一个Excel表…