基于Python+爬虫的旅游景点数据分析推荐系统设计与实现
今天带来的是基于Python+爬虫的旅游景点数据分析推荐系统设计与实现,随着社会日益数据驱动,人们对于个性化体验的需求不断增长,旅游也不例外。通过着眼于设计与实现基于Python Django框架的旅游景点数据分析与推荐系统。传统旅行规划往往需要浏览大量信息以找到合适的目的地和活动。通过利用数据分析技术和个性化推荐算法,该系统旨在通过根据用户的偏好、过去行为和人口统计信息提供量身定制的推荐,简化这
💗博主介绍:✌全网粉丝15W+,CSDN全栈领域优质创作者,博客之星、掘金/知乎/b站/华为云/阿里云等平台优质作者、专注于Java、小程序/APP、python、大数据等技术领域和毕业项目实战,以及程序定制化开发、文档编写、答疑辅导等。
👇🏻 精彩专栏 推荐订阅👇🏻
计算机毕业设计精品项目案例(持续更新)
🌟文末获取源码+数据库+文档🌟
感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以和学长沟通,希望帮助更多的人
一、前言
随着社会日益数据驱动,人们对于个性化体验的需求不断增长,旅游也不例外。通过着眼于设计与实现基于Python Django框架的旅游景点数据分析与推荐系统。
传统旅行规划往往需要浏览大量信息以找到合适的目的地和活动。通过利用数据分析技术和个性化推荐算法,该系统旨在通过根据用户的偏好、过去行为和人口统计信息提供量身定制的推荐,简化这一过程。大量的旅行信息可能导致旅行者决策瘫痪。通过分析和综合相关数据,系统可以为用户提供与其兴趣和偏好相符的目的地、住宿和活动,促进更明智的决策,增强整体旅行规划过程。设计良好的推荐系统可以显著提高用户参与度,提供相关和个性化的内容。通过整合用户反馈机制并持续优化推荐算法,该系统旨在不断提升用户满意度和参与度,从而增强长期用户忠诚度和保留率。
本文拟采用PyCharm开发工具,Python语言Django框架、Echarts可视化技术开发,使用Scrapy-spiders进行数据爬虫,后台使用MySQL数据库进行信息管理,对于各个模块设计制作有一定的安全性。把获取到的数据进行清洗、整合,储存数据到MySQL,然后进行数据可视化的呈现,简单对呈现的图进行数据分析。系统的研究对于推动旅游业的数字化转型和提升用户体验具有重要的意义和价值。
二、功能设计
系统包括多个功能模块,涵盖了用户管理、旅游景点管理、管理员管理、系统管理等方面,以及一些其他辅助功能和信息展示模块。用户管理模块允许管理员管理系统中的用户信息,包括用户的注册、登录、个人资料管理、密码修改等功能。管理员可以查看和编辑用户信息,以及进行必要的权限管理和用户角色分配。旅游景点管理模块允许管理员管理系统中的旅游景点信息,包括景点的添加、编辑、删除等操作。管理员可以维护景点信息的完整性和准确性,并根据需要进行分类和标签管理,以便用户进行搜索和浏览。管理员管理模块用于管理系统中的管理员账户,包括管理员的添加、编辑、删除等操作。管理员可以设置不同管理员的权限和角色,确保系统的安全性和管理的有效性。系统管理模块用于管理系统的整体运行和配置,包括系统设置、日志管理、数据库备份和恢复等功能。管理员可以对系统进行必要的设置和调整,以确保系统的稳定性和安全性。
管理员用例图如图所示。
用户用例图如图所示。
系统功能结构图如下所示:
系统B/S架构原理图:
三、数据设计
概念模型是对现实中的问题出现的事物的进行描述,ER图是由实体及其关系构成的图,通过E-R图可以清楚地描述系统涉及到的实体之间的相互关系。本文将“用户、网络小说、系统简介、公告资讯”等作为实体,它们的局部E-R如图所示:
四、部分效果展示
4.1系统前台功能实现效果
注册登录界面,首先双击打开系统,连上网络之后会显示出本系统的注册登录界面,这是进入系统的第初始页面“注册登录”,能成功进入到该注册登录界面则代表系统的开启是成功的,接下来就可以操作本系统所带有的其他所有的功能,如图所示。
用户登录进入系统可以查看首页、旅游景点、新闻资讯等功能进行详细操作,如图所示。
4.2系统后台管理功能实现效果
管理员功能在旅游景点数据分析与推荐系统中起着重要作用,主要用于管理系统的各项运营和维护工作。管理员拥有特殊的权限,可以对系统进行设置、监控和管理,保障系统的正常运行和安全性。
管理员登录进入系统可以查看首页、用户管理、旅游景点管理、管理员管理、我的信息、在线留言、轮播图管理、新闻资讯、看版等功能进行详细操作。
管理员点击用户管理;在用户管理页面输入用户名、性别、头像、联系电话等信息进行查询,添加或删除用户等操作;如图所示。
管理员点击旅游景点管理;在旅游景点管理页面输入标题、热度、地址、官方电话、等信息,进行查询,添加或删除旅游景点等操作;如图所示。
管理员点击在线留言管理;在在线留言管理页面输入姓名、邮箱、电话等信息,进行查询或删除留言信息等操作;如图所示。
管理员点击新闻资讯管理;在新闻资讯管理页面输入标题、分类名称、发布人、收藏数等信息,进行查询或删除新闻资讯管理等操作;如图所示。
管理员点击关于我们管理页面;在关于我们管理页面输入标题、序号、副标题、图片等信息,进行查询,新增或删除标题等操作;如图所示。
4.3系统数据可视化分析大屏实现效果
管理员点击销售信息管理;在销售信息管理页面输入销售编号、车辆品牌、车辆型号、颜色、销售数量、销售工号、销售姓名、客户姓名、客户电话、销售时间等信息,进行查询,新增或删除销售信息等操作;如图所示。
部分功能代码
# 数据爬取文件
import scrapy
import pymysql
import pymssql
from ..items import LvyoujingdianItem
import time
import re
import random
import platform
import json
import os
import urllib
from urllib.parse import urlparse
import requests
import emoji
# 旅游景点
class LvyoujingdianSpider(scrapy.Spider):
name = 'lvyoujingdianSpider'
spiderUrl = 'https://you.ctrip.com/sight/lanzhou231/s0-p{}.html'
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, '5295r_lvyoujingdian') == 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, '5295r_lvyoujingdian') == 1:
cursor.close()
connect.close()
self.temp_data()
return
list = response.css('div.list_wide_mod2 div.list_mod2')
for item in list:
fields = LvyoujingdianItem()
if '(.*?)' in '''dt a::attr(href)''':
fields["laiyuan"] = re.findall(r'''dt a::attr(href)''', response.text, re.DOTALL)[0].strip()
else:
fields["laiyuan"] = self.remove_html(item.css('dt a::attr(href)').extract_first())
if '(.*?)' in '''div.leftimg a img::attr(src)''':
fields["fengmian"] = re.findall(r'''div.leftimg a img::attr(src)''', response.text, re.DOTALL)[0].strip()
else:
fields["fengmian"] = self.remove_html(item.css('div.leftimg a img::attr(src)').extract_first())
if '(.*?)' in '''div.rdetailbox dl dt a::text''':
fields["biaoti"] = re.findall(r'''div.rdetailbox dl dt a::text''', response.text, re.DOTALL)[0].strip()
else:
fields["biaoti"] = self.remove_html(item.css('div.rdetailbox dl dt a::text').extract_first())
if '(.*?)' in '''b.hot_score_number::text''':
fields["redu"] = re.findall(r'''b.hot_score_number::text''', response.text, re.DOTALL)[0].strip()
else:
fields["redu"] = self.remove_html(item.css('b.hot_score_number::text').extract_first())
if '(.*?)' in '''dd.ellipsis::text''':
fields["dizhi"] = re.findall(r'''dd.ellipsis::text''', response.text, re.DOTALL)[0].strip()
else:
fields["dizhi"] = self.remove_html(item.css('dd.ellipsis::text').extract_first())
if '(.*?)' in '''a.score strong::text''':
fields["pingfen"] = re.findall(r'''a.score strong::text''', response.text, re.DOTALL)[0].strip()
else:
fields["pingfen"] = self.remove_html(item.css('a.score strong::text').extract_first())
if '(.*?)' in '''a.recomment::text''':
fields["pinglun"] = re.findall(r'''a.recomment::text''', response.text, re.DOTALL)[0].strip()
else:
fields["pinglun"] = self.remove_html(item.css('a.recomment::text').extract_first())
if '(.*?)' in '''p[class="bottomcomment ellipsis open_popupbox_a"]''':
fields["dianping"] = re.findall(r'''p[class="bottomcomment ellipsis open_popupbox_a"]''', response.text, re.DOTALL)[0].strip()
else:
fields["dianping"] = self.remove_html(item.css('p[class="bottomcomment ellipsis open_popupbox_a"]').extract_first())
detailUrlRule = item.css('dt 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 class="baseInfoItem"><p class="baseInfoTitle">官方电话</p><p class="baseInfoText">(.*?)</p></div>''':
fields["gfdh"] = re.findall(r'''<div class="baseInfoItem"><p class="baseInfoTitle">官方电话</p><p class="baseInfoText">(.*?)</p></div>''', response.text, re.S)[0].strip()
else:
if 'gfdh' != 'xiangqing' and 'gfdh' != 'detail' and 'gfdh' != 'pinglun' and 'gfdh' != 'zuofa':
fields["gfdh"] = self.remove_html(response.css('''<div class="baseInfoItem"><p class="baseInfoTitle">官方电话</p><p class="baseInfoText">(.*?)</p></div>''').extract_first())
else:
fields["gfdh"] = emoji.demojize(response.css('''<div class="baseInfoItem"><p class="baseInfoTitle">官方电话</p><p class="baseInfoText">(.*?)</p></div>''').extract_first())
except:
pass
try:
if '(.*?)' in '''div[class="detailModule normalModule"]''':
fields["detail"] = re.findall(r'''div[class="detailModule normalModule"]''', response.text, re.S)[0].strip()
else:
if 'detail' != 'xiangqing' and 'detail' != 'detail' and 'detail' != 'pinglun' and 'detail' != 'zuofa':
fields["detail"] = self.remove_html(response.css('''div[class="detailModule normalModule"]''').extract_first())
else:
fields["detail"] = emoji.demojize(response.css('''div[class="detailModule normalModule"]''').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 `lvyoujingdian`(
id
,laiyuan
,fengmian
,biaoti
,redu
,dizhi
,pingfen
,pinglun
,dianping
,gfdh
,detail
)
select
id
,laiyuan
,fengmian
,biaoti
,redu
,dizhi
,pingfen
,pinglun
,dianping
,gfdh
,detail
from `5295r_lvyoujingdian`
where(not exists (select
id
,laiyuan
,fengmian
,biaoti
,redu
,dizhi
,pingfen
,pinglun
,dianping
,gfdh
,detail
from `lvyoujingdian` where
`lvyoujingdian`.id=`5295r_lvyoujingdian`.id
))
limit {0}
'''.format(random.randint(10,15))
cursor.execute(sql)
connect.commit()
connect.close()
源码及文档获取
文章下方名片联系我即可~
大家点赞、收藏、关注、评论啦 、查看👇🏻获取联系方式👇🏻
精彩专栏推荐订阅:在下方专栏👇🏻
最新计算机毕业设计选题篇-选题推荐
小程序毕业设计精品项目案例-200套
Java毕业设计精品项目案例-200套
Python毕业设计精品项目案例-200套
大数据毕业设计精品项目案例-200套
💟💟如果大家有任何疑虑,欢迎在下方位置详细交流。
更多推荐
所有评论(0)