基于Python+大数据的京东教辅书销售数据分析系统设计与实现

💗博主介绍:✌全网粉丝10W+,CSDN全栈领域优质创作者,博客之星、掘金/华为云/阿里云等平台优质作者。
👇🏻 精彩专栏 推荐订阅👇🏻
计算机毕业设计精品项目案例-200套
🌟文末获取源码+数据库+文档🌟
感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以和学长沟通,希望帮助更多的人

一.前言

在这里插入图片描述

本课题拟采用计算机技术设计并开发的京东教辅书销售数据分析系统,主要是为用户提供服务。使得用户可以在系统上查看公告信息、教辅书,管理员对信息进行统一管理,与此同时可以筛选出符合的信息,给笔者提供更符合实际的合理化建议,本课题的意义在于,管理者能通过使用京东教辅书销售数据分析系统,提高工作效率和服务质量,进而提高用户的体验感。

本课题采用PyCharm开发工具,Python语言、Django框架进行开发,后台使用MySQL数据库进行信息管理,设计开发的京东教辅书销售数据分析系统。通过调研和分析,系统拥有管理员和用户两个角色,主要具备注册登录、个人信息修改、用户管理、公告信息管理、教辅书管理、系统管理等功能模块。将纸质管理有效实现为在线管理,极大提高工作效率。


二.技术环境

开发语言:Python
python框架:django
软件版本:python3.7/python3.8
数据库:mysql 5.7或更高版本
数据库工具:Navicat11
爬虫框架:Scrapy
开发软件:PyCharm/vs code
前端框架:vue.js


三.功能设计

在设计系统的过程中,用例图也是系统设计过程中必不可少的模型,如果说系统的结构图可以简洁明了的表示出系统的有关功能模块,那么用例图则可以更为细致的,结合系统中人员的有关分配,能够从细节上描绘出系统中有关功能所完成的具体事件,确切的反映出某个操作以及它们相互之间的内部联系。
其中参与者就是和系统能够发生交互的外在实体,一般可以指系统的某个用户。一个用例图就能对应出系统中的一个功能过程,系统中完整的功能都是由许多不同的用例图所组成的。

在这里插入图片描述在这里插入图片描述

系统功能结构图是系统设计阶段,系统功能结构图只是这个阶段一个基础,整个系统的架构决定了系统的整体模式,是系统的根据。系统总体结构图如图所示。
在这里插入图片描述

四.数据设计

概念模型的设计是为了抽象真实世界的信息,并对信息世界进行建模。它是数据库设计的强大工具。数据库概念模型设计可以通过E-R图描述现实世界的概念模型。系统的E-R图显示了系统中实体之间的链接。而且Mysql数据库是自我保护能力比较强的数据库,下图主要是对数据库实体的E-R图:
在这里插入图片描述
在这里插入图片描述

五.部分效果展示

系统前台功能实现效果

当游客打开系统的网址后,首先看到的就是首页界面。在这里,游客能够看到京东教辅书销售数据分析系统的导航条显示首页、公告信息、教辅书、个人中心。系统首页界面如图所示:

在这里插入图片描述

在系统首页点击中间的注册/登录按钮,然后页面跳转到注册登录界面,后来输入信息完成后,单击注册或者登录操作,如图所示:
在这里插入图片描述

用户点击公告信息,在公告信息页面的搜索栏输入公告标题、公告类型等信息,进行查询,然后可以查看公告标题、公告类型、网页链接、公告图片、公告日期等信息,还可以进行点我收藏等操作;如图所示:
在这里插入图片描述

用户点击教辅书,在教辅书页面的搜索栏输入标题、店铺、出版社等信息,进行查询,然后可以查看来源、标题、价格、店铺、出版社、ISBN、商品编码、封面、浏览时长等信息,详细操作;如图所示:

在这里插入图片描述

后台管理功能实现效果

管理员登录,通过登录页面填写用户名和密码等信息,点击登录操作,如图所示。

在这里插入图片描述

管理员登录进入系统可以查看系统首页、个人中心、用户管理、公告信息管理、教辅书管理、系统管理等功能,进行详细操作,如图所示。
在这里插入图片描述

管理员点击用户管理;在用户管理页面输入用户名、姓名、头像、性别、年龄、手机、地区等信息,进行查询,新增或删除用户信息等操作;如图所示。
在这里插入图片描述

管理员点击公告信息管理;在公告信息管理页面输入公告标题、公告类型、网页链接、公告图片、公告日期等信息,进行查询,新增或删除公告信息等操作;如图所示。

在这里插入图片描述

管理员点击教辅书管理;在教辅书管理页面输入来源、标题、价格、店铺、出版社、ISBN、商品编码、封面、浏览时长等信息,进行查询或导入、删除教辅书等操作;如图所示。
在这里插入图片描述

数据可视化分析大屏展示实现效果

京东教辅书销售数据分析系统的基本情况分析展示,如图所示。

在这里插入图片描述

对于性别统计数据可视化获取之后,开始对性别统计数据进行可视化,下面是通过饼状图对每一个性别统计进行统计分析,如图所示。

在这里插入图片描述

关于地区分布统计,我们以饼状图的形式进行统计展示,如图所示:
在这里插入图片描述

关于出版社统计,我们以饼状图的形式进行统计展示,如图所示:
在这里插入图片描述

关于教辅书(价格TOP10),我们以信息图的形式进行统计展示,如图所示:

在这里插入图片描述

六.部分功能代码

# 数据爬取文件

import scrapy
import pymysql
import pymssql
from ..items import JiaofushuItem
import time
from datetime import datetime,timedelta
import re
import random
import platform
import json
import os
import urllib
from urllib.parse import urlparse
import requests
import emoji

# 教辅书
class JiaofushuSpider(scrapy.Spider):
    name = 'jiaofushuSpider'
    spiderUrl = 'https://search.jd.com/s_new.php?keyword=%E6%95%99%E8%BE%85%E4%B9%A6&wq=%E6%95%99%E8%BE%85%E4%B9%A6&pvid=bc9fbce85b0c4a86a720d0279534847e&page={}&s=56&click=0'
    start_urls = spiderUrl.split(";")
    protocol = ''
    hostname = ''

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def start_requests(self):

        plat = platform.system().lower()
        if plat == 'linux' or plat == 'windows':
            connect = self.db_connect()
            cursor = connect.cursor()
            if self.table_exists(cursor, 'e34e5_jiaofushu') == 1:
                cursor.close()
                connect.close()
                self.temp_data()
                return

        pageNum = 1 + 1
        for url in self.start_urls:
            if '{}' in url:
                for page in range(1, pageNum):
                    next_link = url.format(page)
                    yield scrapy.Request(
                        url=next_link,
                        callback=self.parse
                    )
            else:
                yield scrapy.Request(
                    url=url,
                    callback=self.parse
                )

    # 列表解析
    def parse(self, response):
        
        _url = urlparse(self.spiderUrl)
        self.protocol = _url.scheme
        self.hostname = _url.netloc
        plat = platform.system().lower()
        if plat == 'windows_bak':
            pass
        elif plat == 'linux' or plat == 'windows':
            connect = self.db_connect()
            cursor = connect.cursor()
            if self.table_exists(cursor, 'e34e5_jiaofushu') == 1:
                cursor.close()
                connect.close()
                self.temp_data()
                return

        list = response.css('ul[class="gl-warp clearfix"] li.gl-item')
        
        for item in list:

            fields = JiaofushuItem()



            if '(.*?)' in '''div.p-img a::attr(href)''':
                try:
                    fields["laiyuan"] = re.findall(r'''div.p-img a::attr(href)''', item.extract(), re.DOTALL)[0].strip()
                except:
                    pass
            else:
                fields["laiyuan"] = self.remove_html(item.css('div.p-img a::attr(href)').extract_first())
            if fields["laiyuan"].startswith('//'):
                fields["laiyuan"] = self.protocol + ':' + fields["laiyuan"]
            elif fields["laiyuan"].startswith('/'):
                fields["laiyuan"] = self.protocol + '://' + self.hostname + fields["laiyuan"]
            elif fields["laiyuan"].startswith('http'):
                pass
            else:
                fields["laiyuan"] = self.protocol + '://' + self.hostname + '/' + fields["laiyuan"]
            if '(.*?)' in '''div.p-price strong i::text''':
                try:
                    fields["jiage"] = re.findall(r'''div.p-price strong i::text''', item.extract(), re.DOTALL)[0].strip()
                except:
                    pass
            else:
                fields["jiage"] = self.remove_html(item.css('div.p-price strong i::text').extract_first())

            detailUrlRule = item.css('div.p-img a::attr(href)').extract_first()
            if self.protocol in detailUrlRule:
                pass
            elif detailUrlRule.startswith('//'):
                detailUrlRule = self.protocol + ':' + detailUrlRule
            else:
                detailUrlRule = self.protocol + '://' + self.hostname + detailUrlRule
                # fields["laiyuan"] = detailUrlRule

            yield scrapy.Request(url=detailUrlRule, meta={'fields': fields},  callback=self.detail_parse, dont_filter=True)


    # 详情解析
    def detail_parse(self, response):
        fields = response.meta['fields']

        try:
            if '(.*?)' in '''div.sku-name''':
                fields["biaoti"] = re.findall(r'''div.sku-name''', response.text, re.S)[0].strip()
            else:
                if 'biaoti' != 'xiangqing' and 'biaoti' != 'detail' and 'biaoti' != 'pinglun' and 'biaoti' != 'zuofa':
                    fields["biaoti"] = self.remove_html(response.css('''div.sku-name''').extract_first())
                else:
                    fields["biaoti"] = emoji.demojize(response.css('''div.sku-name''').extract_first())
        except:
            pass


        try:
            if '(.*?)' in '''img#spec-img::attr(data-origin)''':
                fields["fengmian"] = re.findall(r'''img#spec-img::attr(data-origin)''', response.text, re.S)[0].strip()
            else:
                if 'fengmian' != 'xiangqing' and 'fengmian' != 'detail' and 'fengmian' != 'pinglun' and 'fengmian' != 'zuofa':
                    fields["fengmian"] = self.remove_html(response.css('''img#spec-img::attr(data-origin)''').extract_first())
                else:
                    fields["fengmian"] = emoji.demojize(response.css('''img#spec-img::attr(data-origin)''').extract_first())
        except:
            pass

        if fields["fengmian"].startswith('//'):
            fields["fengmian"] = self.protocol + ':' + fields["fengmian"]
        elif fields["fengmian"].startswith('/'):
            fields["fengmian"] = self.protocol + '://' + self.hostname + fields["fengmian"]

        try:
            if '(.*?)' in '''ul[class="parameter2 p-parameter-list"] li:nth-child(1)::attr(title)''':
                fields["dianpu"] = re.findall(r'''ul[class="parameter2 p-parameter-list"] li:nth-child(1)::attr(title)''', response.text, re.S)[0].strip()
            else:
                if 'dianpu' != 'xiangqing' and 'dianpu' != 'detail' and 'dianpu' != 'pinglun' and 'dianpu' != 'zuofa':
                    fields["dianpu"] = self.remove_html(response.css('''ul[class="parameter2 p-parameter-list"] li:nth-child(1)::attr(title)''').extract_first())
                else:
                    fields["dianpu"] = emoji.demojize(response.css('''ul[class="parameter2 p-parameter-list"] li:nth-child(1)::attr(title)''').extract_first())
        except:
            pass


        try:
            if '(.*?)' in '''li[clstag="shangpin|keycount|product|chubanshe_3"] a::text''':
                fields["chubanshe"] = re.findall(r'''li[clstag="shangpin|keycount|product|chubanshe_3"] a::text''', response.text, re.S)[0].strip()
            else:
                if 'chubanshe' != 'xiangqing' and 'chubanshe' != 'detail' and 'chubanshe' != 'pinglun' and 'chubanshe' != 'zuofa':
                    fields["chubanshe"] = self.remove_html(response.css('''li[clstag="shangpin|keycount|product|chubanshe_3"] a::text''').extract_first())
                else:
                    fields["chubanshe"] = emoji.demojize(response.css('''li[clstag="shangpin|keycount|product|chubanshe_3"] a::text''').extract_first())
        except:
            pass


        try:
            if '(.*?)' in '''</li>.*<li title="(.*?)">ISBN:''':
                fields["isbn"] = re.findall(r'''</li>.*<li title="(.*?)">ISBN:''', response.text, re.S)[0].strip()
            else:
                if 'isbn' != 'xiangqing' and 'isbn' != 'detail' and 'isbn' != 'pinglun' and 'isbn' != 'zuofa':
                    fields["isbn"] = self.remove_html(response.css('''</li>.*<li title="(.*?)">ISBN:''').extract_first())
                else:
                    fields["isbn"] = emoji.demojize(response.css('''</li>.*<li title="(.*?)">ISBN:''').extract_first())
        except:
            pass


        try:
            if '(.*?)' in '''</li>.*<li title='(.*?)'>商品编码:''':
                fields["spbm"] = re.findall(r'''</li>.*<li title='(.*?)'>商品编码:''', response.text, re.S)[0].strip()
            else:
                if 'spbm' != 'xiangqing' and 'spbm' != 'detail' and 'spbm' != 'pinglun' and 'spbm' != 'zuofa':
                    fields["spbm"] = self.remove_html(response.css('''</li>.*<li title='(.*?)'>商品编码:''').extract_first())
                else:
                    fields["spbm"] = emoji.demojize(response.css('''</li>.*<li title='(.*?)'>商品编码:''').extract_first())
        except:
            pass




        return fields

    # 去除多余html标签
    def remove_html(self, html):
        if html == None:
            return ''
        pattern = re.compile(r'<[^>]+>', re.S)
        return pattern.sub('', html).strip()

    # 数据库连接
    def db_connect(self):
        type = self.settings.get('TYPE', 'mysql')
        host = self.settings.get('HOST', 'localhost')
        port = int(self.settings.get('PORT', 3306))
        user = self.settings.get('USER', 'root')
        password = self.settings.get('PASSWORD', '123456')

        try:
            database = self.databaseName
        except:
            database = self.settings.get('DATABASE', '')

        if type == 'mysql':
            connect = pymysql.connect(host=host, port=port, db=database, user=user, passwd=password, charset='utf8')
        else:
            connect = pymssql.connect(host=host, user=user, password=password, database=database)

        return connect

    # 断表是否存在
    def table_exists(self, cursor, table_name):
        cursor.execute("show tables;")
        tables = [cursor.fetchall()]
        table_list = re.findall('(\'.*?\')',str(tables))
        table_list = [re.sub("'",'',each) for each in table_list]

        if table_name in table_list:
            return 1
        else:
            return 0

    # 数据缓存源
    def temp_data(self):

        connect = self.db_connect()
        cursor = connect.cursor()
        sql = '''
            insert into `jiaofushu`(
                id
                ,laiyuan
                ,biaoti
                ,fengmian
                ,jiage
                ,dianpu
                ,chubanshe
                ,isbn
                ,spbm
            )
            select
                id
                ,laiyuan
                ,biaoti
                ,fengmian
                ,jiage
                ,dianpu
                ,chubanshe
                ,isbn
                ,spbm
            from `e34e5_jiaofushu`
            where(not exists (select
                id
                ,laiyuan
                ,biaoti
                ,fengmian
                ,jiage
                ,dianpu
                ,chubanshe
                ,isbn
                ,spbm
            from `jiaofushu` where
                `jiaofushu`.id=`e34e5_jiaofushu`.id
            ))
            limit {0}
        '''.format(random.randint(10,15))

        cursor.execute(sql)
        connect.commit()

        connect.close()


最后

最新计算机毕业设计选题篇-选题推荐(值得收藏)
计算机毕业设计精品项目案例-200套(值得订阅)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一点毕设

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值