基于大数据+Hadoop的豆瓣电子图书推荐系统实现

🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄

🌹简历模板、学习资料、面试题库、技术互助

🌹文末获取联系方式 📝

在这里插入图片描述


系列文章目录

基于大数据+Hadoop的豆瓣电子图书推荐系统实现


文章目录

  • 系列文章目录
  • 1、前言介绍
  • 2、功能设计
  • 3、功能实现
  • 库表设计
  • 5、关键代码
  • 6、Lunwen参考
  • 往期热门专栏回顾


1、前言介绍

随着信息技术的飞速发展,特别是互联网和移动通信技术的普及,数字化阅读逐渐成为人们获取知识和信息的重要方式。在这样的背景下,电子图书以其便捷性和丰富性受到了广泛欢迎。随着电子图书市场的不断扩大,书籍的种类和数量也在急剧增加,这为用户挑选书籍带来了挑战。为了解决信息过载的问题,个性化推荐系统应运而生,并逐渐成为在线阅读平台不可或缺的一部分。基于用户历史行为数据进行推荐的协同过滤算法尤为流行。处理庞大的用户群体和海量的图书数据需要强大的计算能力,传统的单机计算模式已无法满足需求。Hadoop作为一个开源的分布式计算平台,以其高容错性、高扩展性和对大数据处理的优秀能力,成为大数据分析的首选工具。因此,利用Hadoop来构建电子图书推荐系统,不仅可以有效处理和分析大规模数据集,提升推荐质量,还能保证系统的可扩展性和稳定性。

在这里插入图片描述
基于Hadoop的豆瓣电子图书推荐系统的研究与实现能够为用户提供更加精准和个性化的阅读推荐,从而优化用户体验,提高用户满意度和平台黏性。通过分析用户的历史阅读行为和偏好,系统可以发现用户的阅读模式,进而推荐更符合个人兴趣的书籍,帮助用户节省筛选时间,增强阅读效率。对于电子图书平台来说,一个高效的推荐系统可以促进更多优质内容的分发,增加用户流量和书籍销量,从而带动平台的经济效益。该系统的建立还有助于推动数据挖掘和机器学习技术在实际应用中的发展,为相关领域提供宝贵的实践经验和研究成果。最后,随着数据处理技术的不断进步,该研究还可以为未来电子图书推荐系统的改进提供理论基础和技术支持,具有长远的研究和应用价值。

2、功能设计

系统的功能设计是整个系统的运行基础,是一个把设计需求替换成以计算机系统的形式表示出来。通过对豆瓣电子图书推荐系统的调查、分析和研究,得出了该系统的总体规划,这是开发设计系统的初步核心。如下图所示:
在这里插入图片描述
爬虫数据集展示:
在这里插入图片描述

3、功能实现

在这里插入图片描述
当人们打开系统的网址后,首先看到的就是首页界面。在这里,人们能够看到系统的导航条,通过导航条导航进入各功能展示页面进行操作。系统首页界面如图5-1所示:
在这里插入图片描述
在注册流程中,用户在Vue前端填写必要信息(如用户名、密码等)并提交。前端将这些信息通过HTTP请求发送到Java后端。后端处理这些信息,检查用户名是否唯一,并将新用户数据存入MySQL数据库。完成后,后端向前端发送注册成功的确认,前端随后通知用户完成注册。这个过程实现了新用户的数据收集、验证和存储。注册页面如图5-2所示:
在这里插入图片描述

图5-2注册详细页面

豆瓣高分:在豆瓣高分页面的输入栏中输入书名、作者、出版社和标签进行查询,可以查看到豆瓣高分详细信息,并进行评论或收藏操作;豆瓣高分页面如图5-3所示:
在这里插入图片描述

图5-3豆瓣高分详细页面

个人中心:在个人中心页面可以对个人中心、修改密码、我的发布、我的收藏等进行详细操作;如图5-4所示:
在这里插入图片描述
在登录流程中,用户首先在Vue前端界面输入用户名和密码。这些信息通过HTTP请求发送到Java后端。后端接收请求,通过与MySQL数据库交互验证用户凭证。如果认证成功,后端会返回给前端,允许用户访问系统。这个过程涵盖了从用户输入到系统验证和响应的全过程。如图5-5所示。

用户管理功能在视图层(view层)进行交互,比如点击“查询、添加或删除”按钮或填写用户信息表单。这些用户表单动作被视图层捕获并作为请求发送给相应的控制器层(controller层)。控制器接收到这些请求后,调用服务层(service层)以执行相关的业务逻辑,例如验证输入数据的有效性和与数据库的交互。服务层处理完这些逻辑后,进一步与数据访问对象层(DAO层)交互,后者负责具体的数据操作如查看、修改或删除用户信息,并将操作结果返回给控制器。最终,控制器根据这些结果更新视图层,以便用户功能可以看到最新的信息或相应的操作反馈。如图5-7所示:
在这里插入图片描述

图5-7用户管理界面

豆瓣高分管理功能在视图层(view层)进行交互,比如点击“查询、添加、删除或爬取数据”按钮或填写豆瓣高分信息表单。这些豆瓣高分表单动作被视图层捕获并作为请求发送给相应的控制器层(controller层)。控制器接收到这些请求后,调用服务层(service层)以执行相关的业务逻辑,例如验证输入数据的有效性和与数据库的交互。服务层处理完这些逻辑后,进一步与数据访问对象层(DAO层)交互,后者负责具体的数据操作如查看、修改、查看评论或删除豆瓣高分信息,并将操作结果返回给控制器。最终,控制器根据这些结果更新视图层,以便豆瓣高分功能可以看到最新的信息或相应的操作反馈。如图5-8所示:
在这里插入图片描述

图5-8豆瓣高分管理界面

管理员进行爬取数据后,点击主页面右上角的看板,可以查看到系统简介、书名、作者统计、价格统计、出版社、评分统计、豆瓣高分总数、豆瓣高分信息等实时的分析图进行可视化管理;如图5-9所示:
在这里插入图片描述

图5-9看板界面

库表设计

表4-11:豆瓣高分
在这里插入图片描述

5、关键代码

# # -*- coding: utf-8 -*-# 数据爬取文件import scrapy
import pymysql
import pymssql
from ..items import DianzitushuItem
import time
from datetime import datetime,timedelta
import datetime as formattime
import re
import random
import platform
import json
import os
import urllib
from urllib.parse import urlparse
import requests
import emoji
import numpy as np
import pandas as pd
from sqlalchemy import create_engine
from selenium.webdriver import ChromeOptions, ActionChains
from scrapy.http import TextResponse
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
# 电子图书
class DianzitushuSpider(scrapy.Spider):name = 'dianzitushuSpider'spiderUrl = 'https://read.douban.com/j/kind/'start_urls = spiderUrl.split(";")protocol = ''hostname = ''realtime = Falsedef __init__(self,realtime=False,*args, **kwargs):super().__init__(*args, **kwargs)self.realtime = realtime=='true'def start_requests(self):plat = platform.system().lower()if not self.realtime and (plat == 'linux' or plat == 'windows'):connect = self.db_connect()cursor = connect.cursor()if self.table_exists(cursor, '0n4b129m_dianzitushu') == 1:cursor.close()connect.close()self.temp_data()returnpageNum = 1 + 1for 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.schemeself.hostname = _url.netlocplat = platform.system().lower()if not self.realtime and (plat == 'linux' or plat == 'windows'):connect = self.db_connect()cursor = connect.cursor()if self.table_exists(cursor, '0n4b129m_dianzitushu') == 1:cursor.close()connect.close()self.temp_data()returndata = json.loads(response.body)try:list = data["list"]except:passfor item in list:fields = DianzitushuItem()try:fields["title"] = emoji.demojize(self.remove_html(str( item["title"] )))except:passtry:fields["picture"] = emoji.demojize(self.remove_html(str( item["cover"] )))except:passtry:fields["salesprice"] = float( item["salesPrice"]/100)except:passtry:fields["wordcount"] = int( item["wordCount"])except:passtry:fields["author"] = emoji.demojize(self.remove_html(str(','.join(str(i['name']) for i in  item["author"]) )))except:passtry:fields["biaoqian"] = emoji.demojize(self.remove_html(str( item.get("biaoqian", "小说") )))except:passtry:fields["detailurl"] = emoji.demojize(self.remove_html(str('https://read.douban.com'+ item["url"] )))except:passdetailUrlRule = item["url"]if '["url"]'.startswith('http'):if '{0}' in '["url"]':detailQueryCondition = []detailUrlRule = '["url"]'i = 0while i < len(detailQueryCondition):detailUrlRule = detailUrlRule.replace('{' + str(i) + '}', str(detailQueryCondition[i]))i += 1else:detailUrlRule =item["url"]detailUrlRule ='https://read.douban.com'+ detailUrlRuleif detailUrlRule.startswith('http') or self.hostname in detailUrlRule:passelse:detailUrlRule = self.protocol + '://' + self.hostname + detailUrlRulefields["laiyuan"] = detailUrlRuleyield scrapy.Request(url=detailUrlRule, meta={'fields': fields}, callback=self.detail_parse)# 详情解析def detail_parse(self, response):fields = response.meta['fields']try:if '(.*?)' in '''span[itemprop="genre"]::text''':fields["genre"] = str( re.findall(r'''span[itemprop="genre"]::text''', response.text, re.S)[0].strip())else:if 'genre' != 'xiangqing' and 'genre' != 'detail' and 'genre' != 'pinglun' and 'genre' != 'zuofa':fields["genre"] = str( self.remove_html(response.css('''span[itemprop="genre"]::text''').extract_first()))else:try:fields["genre"] = str( emoji.demojize(response.css('''span[itemprop="genre"]::text''').extract_first()))except:passexcept:passtry:fields["chubanshe"] = str( response.xpath('''//span[text()="出版社"]/../span[@class="labeled-text"]/span[1]/text()''').extract()[0].strip())except:passtry:fields["cbsj"] = str( response.xpath('''//span[text()="出版社"]/../span[@class="labeled-text"]/span[2]/text()''').extract()[0].strip())except:passtry:if '(.*?)' in '''a[itemprop="provider"]::text''':fields["provider"] = str( re.findall(r'''a[itemprop="provider"]::text''', response.text, re.S)[0].strip())else:if 'provider' != 'xiangqing' and 'provider' != 'detail' and 'provider' != 'pinglun' and 'provider' != 'zuofa':fields["provider"] = str( self.remove_html(response.css('''a[itemprop="provider"]::text''').extract_first()))else:try:fields["provider"] = str( emoji.demojize(response.css('''a[itemprop="provider"]::text''').extract_first()))except:passexcept:passtry:if '(.*?)' in '''span.score::text''':fields["score"] = float( re.findall(r'''span.score::text''', response.text, re.S)[0].strip())else:if 'score' != 'xiangqing' and 'score' != 'detail' and 'score' != 'pinglun' and 'score' != 'zuofa':fields["score"] = float( self.remove_html(response.css('''span.score::text''').extract_first()))else:try:fields["score"] = float( emoji.demojize(response.css('''span.score::text''').extract_first()))except:passexcept:passtry:if '(.*?)' in '''span.amount::text''':fields["pingjiashu"] = int( re.findall(r'''span.amount::text''', response.text, re.S)[0].strip().replace('评价',''))else:if 'pingjiashu' != 'xiangqing' and 'pingjiashu' != 'detail' and 'pingjiashu' != 'pinglun' and 'pingjiashu' != 'zuofa':fields["pingjiashu"] = int( self.remove_html(response.css('''span.amount::text''').extract_first()).replace('评价',''))else:try:fields["pingjiashu"] = int( emoji.demojize(response.css('''span.amount::text''').extract_first()).replace('评价',''))except:passexcept:passreturn fields# 数据清洗def pandas_filter(self):engine = create_engine('mysql+pymysql://root:123456@localhost/spider0n4b129m?charset=UTF8MB4')df = pd.read_sql('select * from dianzitushu limit 50', con = engine)# 重复数据过滤df.duplicated()df.drop_duplicates()#空数据过滤df.isnull()df.dropna()# 填充空数据df.fillna(value = '暂无')# 异常值过滤# 滤出 大于800 和 小于 100 的a = np.random.randint(0, 1000, size = 200)cond = (a<=800) & (a>=100)a[cond]# 过滤正态分布的异常值b = np.random.randn(100000)# 3σ过滤异常值,σ即是标准差cond = np.abs(b) > 3 * 1b[cond]# 正态分布数据df2 = pd.DataFrame(data = np.random.randn(10000,3))# 3σ过滤异常值,σ即是标准差cond = (df2 > 3*df2.std()).any(axis = 1)# 不满⾜条件的⾏索引index = df2[cond].index# 根据⾏索引,进⾏数据删除df2.drop(labels=index,axis = 0)# 去除多余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.databaseNameexcept: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 1else:return 0# 数据缓存源def temp_data(self):connect = self.db_connect()cursor = connect.cursor()sql = '''insert into `dianzitushu`(id,title,picture,salesprice,wordcount,author,biaoqian,detailurl,genre,chubanshe,cbsj,provider,score,pingjiashu)selectid,title,picture,salesprice,wordcount,author,biaoqian,detailurl,genre,chubanshe,cbsj,provider,score,pingjiashufrom `0n4b129m_dianzitushu`where(not exists (selectid,title,picture,salesprice,wordcount,author,biaoqian,detailurl,genre,chubanshe,cbsj,provider,score,pingjiashufrom `dianzitushu` where`dianzitushu`.id=`0n4b129m_dianzitushu`.id))order by rand()limit 50;'''cursor.execute(sql)connect.commit()connect.close()

6、Lunwen参考

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


往期热门专栏回顾

专栏描述
Java项目实战介绍Java组件安装、使用;手写框架等
Aws服务器实战Aws Linux服务器上操作nginx、git、JDK、Vue
Java微服务实战Java 微服务实战,Spring Cloud Netflix套件、Spring Cloud Alibaba套件、Seata、gateway、shadingjdbc等实战操作
Java基础篇Java基础闲聊,已出HashMap、String、StringBuffer等源码分析,JVM分析,持续更新中
Springboot篇从创建Springboot项目,到加载数据库、静态资源、输出RestFul接口、跨越问题解决到统一返回、全局异常处理、Swagger文档
Spring MVC篇从创建Spring MVC项目,到加载数据库、静态资源、输出RestFul接口、跨越问题解决到统一返回
华为云服务器实战华为云Linux服务器上操作nginx、git、JDK、Vue等,以及使用宝塔运维操作添加Html网页、部署Springboot项目/Vue项目等
Java爬虫通过Java+Selenium+GoogleWebDriver 模拟真人网页操作爬取花瓣网图片、bing搜索图片等
Vue实战讲解Vue3的安装、环境配置,基本语法、循环语句、生命周期、路由设置、组件、axios交互、Element-ui的使用等
Spring讲解Spring(Bean)概念、IOC、AOP、集成jdbcTemplate/redis/事务等

资料获取,更多粉丝福利,关注下方公众号获取

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

手动实现简易版RPC(四)

手动实现简易版RPC(四) 往期内容 手动实现简易版RPC&#xff08;一&#xff09;&#xff1a;RPC简介及系统架构 手动实现简易版RPC&#xff08;二&#xff09;&#xff1a;简单RPC框架实现 手动实现简易版RPC(三)&#xff1a;mock数据生成 前言 接上几篇博客我们实现了最…

便签怎么设置不同的标签 便签创建不同分组标签的方法

在日常工作和生活中&#xff0c;便签已成为我随身携带的小助手。每当灵感闪现&#xff0c;或是需要临时记录一些重要事项&#xff0c;我都会随手打开便签&#xff0c;快速记录下来。然而&#xff0c;随着记录的内容越来越多&#xff0c;如何高效地管理和查找这些信息成为了一个…

联丰策略股票炒股市场港股恒生指数止步“10连阳”

查查配港股市场今日未能持续之前的上涨趋势。恒生指数在经历了4月22日至5月6日的“十日连阳”罕见行情后,其反弹动能有所减弱。与此同时,恒生科技指数也遭遇了回调。截至收盘,恒生指数跌0.53%,报收18479.37点;科技指数跌2.13%,报收3922.54点;国企指数跌0.70%,报收6526.67点。 …

【保姆级详细步骤教学用DOSBoxV0.74写出一个汇编语言程序输出Hello World!】

使用任何文本编辑器创建一个名为 HELLO.ASM 的文件&#xff0c;并将以下代码粘贴到文件中&#xff1a; .MODEL SMALL .STACK 100H.DATAMSG DB Hello, World!, $PROMPT DB 13, 10, Press any key to exit..., $.CODEMAIN PROCMOV AX, DATAMOV DS, AXMOV AH, 09HLEA DX, MSGINT …

R语言【Tidyverse、Tidymodel】机器学习

机器学习已经成为继理论、实验和数值计算之后的科研“第四范式”&#xff0c;是发现新规律&#xff0c;总结和分析实验结果的利器。机器学习涉及的理论和方法繁多&#xff0c;编程相当复杂&#xff0c;一直是阻碍机器学习大范围应用的主要困难之一&#xff0c;由此诞生了Python…

2024最详细全面的发卡平台对比调研

最近在调研目前市面上的发卡平台&#xff0c;对一些主流的托管式发卡平台与github上开源的发卡项目做了横向对比&#xff0c;本文主要介绍各自特点以及需要注意避免的坑。 直接上表格&#xff0c;一目了然。 对比独角数卡***发卡/泛发卡平台iDataRiver发卡稳定性/跑路风险自己…

双层胶工艺是什么?

知 识星球&#xff08;星球名&#xff1a; 芯片制造与封测社区&#xff0c;星球号&#xff1a; 63559049&#xff09;里的学员问&#xff1a; 什么是双层胶工艺&#xff1f; 为什么要用双层胶呢&#xff1f; 本图由allresist公司提供&#xff0c;特此鸣谢 为什么要涂双层…

【机器学习与实现】线性回归示例——波士顿房价分析

目录 一、创建Pandas对象并查看数据的基本情况二、使用皮尔逊相关系数分析特征之间的相关性三、可视化不同特征与因变量MEDV&#xff08;房价中值&#xff09;间的相关性四、划分训练集和测试集并进行回归分析 一、创建Pandas对象并查看数据的基本情况 boston.csv数据集下载&a…

Proxmox VE 8 SDN创建VLAN隔离用户网络

作者&#xff1a;田逸&#xff08;formyz&#xff09; 在上一篇文章中&#xff0c;我们用SDN的Simple对租户&#xff08;用户&#xff09;网络实现了隔离功能&#xff0c;但它有个限制&#xff0c;仅仅能在单个物理节点上进行通信&#xff0c;而不能跨越物理节点&#xff08;除…

天诚再出学校物联网锁新品,打造AIoT高校数智化通行解决方案

为进一步提升高职及本科院校校园安防智能化管理水平&#xff0c;助力学校教育信息化转变&#xff0c;校园全场景AIoT解决方案服务商——江苏新巢天诚智能技术有限公司&#xff08;以下简称“天诚”&#xff09;推出系列校园物联网锁新品&#xff0c;为在校师生用户群体提供更多…

24_Scala集合Map

文章目录 Scala集合Map1.构建Map2.增删改查3.Map的get操作细节 Scala集合Map –默认immutable –概念和Java一致 1.构建Map –创建kv键值对 && kv键值对的表达 –创建immutable map –创建mutable map //1.1 构建一个kv键值对 val kv "a" -> 1 print…

数据挖掘流程是怎样的?数据挖掘平台基本功能有哪些?

数据挖掘是从大量的、不完全的、有噪声的、模糊的、随机的数据中提取隐含在其中的、人们事先不知道的、但又是潜在有用的信息和知识的过程。 数据挖掘的流程是&#xff1a; 清晰地定义出业务问题&#xff0c;确定数据挖掘的目的。 数据准备: 数据准备包括&am…

《ElementUI 基础知识》el-tree 之“我的电脑”目录结构效果

前言 项目需求&#xff0c;Web 端获取服务器文件夹目录结构。目录数据是调接口获取&#xff0c;本篇略过&#xff0c;直接展现数据&#xff01; 效果 实现 html 代码 8 - 15 行&#xff0c;自定义节点信息&#xff1b;代码 9 - 14 行&#xff0c;判断 icon 显示&#xff1b…

数据结构学不会?数据结构可视化网站来了

目录 前言 图码网站 算法可视化 算法编辑器 数据结构全书 数据结构课程 总结 前言 数据结构与算法在计算机的学习中应该是许多小白最头疼的东西&#xff0c;明明听的时候那么容易&#xff0c;为什么转换成代码就那么抽象呢&#xff1f; 有没有一个网站可以数据结构与算…

C语言——文件描述符、系统调用操作文件

文件描述符 在Unix-like操作系统中&#xff0c;文件描述符&#xff08;file descriptor&#xff09;是一个用于标识打开文件或I/O设备的整数值。它是对底层文件系统的抽象&#xff0c;用于在应用程序和操作系统之间传递文件信息。 文件描述符是一个非负整数&#xff0c;通常是…

FX110书籍推荐:如何快速成为一名专业股票投资人?

股票投资领域有一本神作《股票交易入门》&#xff0c;它是股票从业人员的入门必备书籍。 关于股票入门的书籍很多&#xff0c;但这本书涉及的知识面最全、实用性最强。从这本书里&#xff0c;我们可以领略到股票交易世界的跌宕起伏而又波澜壮阔的魅力。本书作者 本书的作者是美…

【自动驾驶|毫米波雷达】卡尔曼滤波

目录 一. 滤波器分类 二.卡尔曼滤波&#xff08;Kalman Filter&#xff09;原理 &#xff08;1&#xff09;定性理解 &#xff08;2&#xff09;定量推导 1. 预测阶段 2. 更新阶段 3. 卡尔曼增益 1&#xff09;卡尔曼增益 2&#xff09;如何理解卡尔曼增益&#xff1f; 三…

省份数量00

题目链接 省份数量 题目描述 注意点 1 < n < 200isConnected[i][j] 为 1 或 0isConnected[i][i] 1isConnected[i][j] isConnected[j][i] 解答思路 最初想到的是广度优先遍历&#xff0c;当某个城市不属于省份&#xff0c;需要从该城市开始&#xff0c;根据isConne…

重大消息!软考高级论文单考,综合和案例连考

依据辽宁省信息技术教育中心&#xff08;辽宁省软考办&#xff09;发布《关于2024年上半年计算机技术与软件专业技术资格(水平)考试批次安排的通知》可知&#xff0c;2024年上半年软考有如下调整&#xff1a; 1.软考高级考试中&#xff0c;综合知识和案例分析连考&#xff08;…

【功耗仪使用】

一&#xff0c;功耗仪使用 1.1&#xff0c;功耗仪外观及与手机&#xff0c;电脑连接方式 power monitor设备图 同时power monitor设备的后端有一个方形插孔通过数据线与电脑主机USB接口相连接&#xff0c;圆形插孔为电源插孔&#xff0c;用来给power monitor设备通电 pow…