基于hive数据仓库的贵州旅游景点数据分析系统的设计与实现
摘 要
随着旅游业的快速发展和数字化转型,旅游数据的收集和分析变得越来越重要。贵州省作为一个拥有丰富旅游资源的地区,旅游数据的分析对于促进旅游业的发展和提升旅游体验具有重要意义。基于Hive数据仓库的贵州省旅游景点数据分析系统的设计与实现,旨在建立一个高效、可靠且功能丰富的系统,帮助利益相关者准确理解和利用旅游数据,为决策和规划提供可靠依据。
本系统通过数据采集与存储模块,将贵州省的旅游景点数据收集到一个中心化的数据平台,确保数据的准确性和一致性。同时,借助Hive数据仓库的设计,实现了灵活的数据模型和高效的数据查询与分析能力。系统的功能模块设计包括数据导入模块和查询与分析模块,前者实现了对新数据的导入和预处理,后者提供了多维度的数据查询和分析功能。
关键词:hive 旅游
1.1研究背景及意义
贵州省作为中国的旅游目的地之一,拥有丰富多样的自然景观和独特的民族文化,吸引了大量的游客前来观光和旅游。如今,随着旅游业的迅速发展和智能化技术的进步,对于旅游数据的分析和利用变得越来越重要。然而,目前尚缺乏一个完备的贵州省旅游景点数据分析系统,以全面、准确地了解和管理贵州省的旅游景点数据,为相关决策提供支持和参考。
本项目的目的是基于Hive数据仓库,设计和实现一个贵州省旅游景点数据分析系统,旨在为用户提供方便、快捷的数据分析和查询功能,帮助相关人员深入了解贵州省旅游景点的情况,提供数据支持和参考,促进旅游业的持续发展。
总之,贵州省旅游景点数据分析系统的设计与实现将为贵州旅游业的发展带来巨大的推动力,为决策者提供科学的决策依据,提升景区的运营效率和服务质量,进一步提升贵州省作为旅游目的地的知名度和吸引力。
1.2 开发现状
国外与国内相比下来,国外由于互联网很早就拥有了分析系统,因此,他们对于旅游分析系统方面的研究远比国内深入,而纵观几十年来的科技发展,可以很清楚的看到他们的旅游分析系统的发展阶段,具体可以分为三个阶段。
- 初始阶段:1959年IBM公司的销售员R. Blair Smith建议美国航空公司总裁C.R.Smith一起去开发一个计算机订位系统(SABRE),1960年世界首个计算机订位系统诞生。
- 发展阶段:由于科技的发展,1979年-1995年这期间很多机票的购买,酒店预订,乘车等事务都可以通过网络来完成,这让旅游系统得到更多的关注,大大推进了旅游网站的发展.
- 高潮阶段:旅游文化的兴起,1995年世界旅游组织,以及国外多个旅游机构举办了世界信息技术与旅游会议,体现出计算机与旅游业密不可分的关系。
国内的旅游信息化与国外相比由于起步较晚以及多种原因,等到改革开放后才开始有这方面的研究,即使起步晚经过国人的不断学习与研究,在旅游信息化科技发展方面已经堪比国外大国了。国内旅游网站发展可以分为三个阶段。
- 萌芽阶段:由于改革开放,大量国外旅游文化与科技涌入国内,1998年-2002年在互联网技术发展蓬勃时,旅游网站也因此出现在人们的视野
- 发展阶段:以前国内旅游网站主要以服务为主,在2003年-2008年这期间由于互联网的飞速发展,在以往以服务为主的基础上加上了旅游路线,以及在线旅游模式,这让国内旅游网站的用户迎来了爆发式的增长。
- 成熟阶段:从2008年以后,旅游网站已经成了我国游客必不可少的工具,即使已经成熟,但是仍然在稳步发展。
2 开发工具及相关技术
2.1 Hive描述
Apache Hive是一个容错,分布式的数仓系统,可实现大规模分析。 而且Hive 元存储(HMS)提供了一个元数据的中央存储库,可以很快速的分析并做出有用的信息和数据驱动的决策,因此它也是很多数据湖架构的关键组成部分。 Hive通过Apache Hadoop建立,再由hdfs支持S3,adls,gs等存储。除此之外Hive 还允许用户使用 SQL 读取、写入和管理数据。
优点:
- Hive不用去写MapReduce,大大减少了程序员的学习成本。
- Hive可以更好地处理大数据,由于延迟高的问题,处理小数据没有优势。
- Hive简单,易上手,拥有快速开发的能力
- 支持用户自定义函数
缺点:
- 调优困难
- 不擅长数据挖掘
- 不能表达迭代算法
2.2 MySQL描述
MySQL是一个DBMS(数据库管理系统)。由于它的体积小,总体拥有成本低,速度快,开放源码等特点,也让它成为了当前最流行的关系型数据库管理系统,很多中小型的网站开发者都会用MySQL使用SQL语言操作,将MySQL作为网站数据库。
优点:
- 体积小,总体拥有低,速度快,开放源码。
- 核心采用多线程编程,使用多线程实现MySQL可以充分利用CPU资源。
- 支持Windows,Linux,HP-UX,OpenBSD等多种操作系统。
- MySQL有安全的权限和口令系统,支持主机认证。
缺点:
- 不支持自定义数据类型。
- 安全系统过于复杂。
- 对触发器支持和存储过程不友好。
- 不能备份。
2.3 Spring Boot概述
Spring Boot是一个快速开发的框架。用于简化加快Spring应用的建立,运行,调节测试和安装部署。可以更好地解决依赖问题,简化并且加快了Java web的开发,让开发人员可以更合理的运用自己的开发时间。
优点:
- 能够快速建立项目。
- 提高了开发和部署的效率。
- 不用外部依赖Servlet容器也可以独立运行。
- 不用配置也可以也可以对主流开发框架进行开发。
2.4 Pycharm简介
Pycharm是一种Python IDE,是Python语言的高效率开发工具,如项目管理,调试,单元测试,代码跳转,版本控制,智能提示等。
优点:
- 支持web框架开发,如Flask,Pyramid,Django。
- 能够快速精确地修复bug。
- 可在远程主机上进行程序开发。
缺点:
- 界面过于复杂。
- 成本过高。
2.5 Vue.js 描述
Vue是一款用于构建用户界面的JavaScript框架。他基于CSS,HTML,JavaScript构建。可以高效的构建想要的界面。还是一个渐进式框架,可以逐步集成且相当灵活。
优点:
- 能够修改和使用现有的应用程序。
- 无论简单还是复杂都能够集成小部件且不会影响系统。
- 可以更好的编辑文档。
- 具有很强的适应性。
缺点:
- 不支持IE8。
- 存在程序开发问题。
(1)技术方面,本系统使用了Hive,MySQL技术来支持数据逻辑与事务,P然后前台的页面显示用H5来做,Python来爬取数据,Spring Boot做前端的框架。这些技术都由本人在课堂上经过学习积累所得以及一些编程网站学习所得。这些技术都有在课堂上做不同的项目实践过,可以更好地开发系统。从技术方面来看,这个系统是可以实现的。
(2)经济方面,因为这个系统的目的是为游客提供更好的旅游路线以及购票服务,还有工作人员更好的管理后台,这就是我们能够直接使用信息化软件,而且这个系统主要成本集中于对数据后期的维护和管理,他所提供的高效率和低成本远远低于一般的系统。同时也可以很明显的发现这个系统的实际应用方面的价值已经超过了系统实际开发和维护所需的成本,因此从经济上说,本系统是可行的。
(3)实用方面,本系统包含了购票,评论,相关景点推荐,在当前大时代是紧跟时代潮流的,还有更优的旅游路线,游客可以通过互联网更清晰的了解到自己需要的东西,并且非常便捷和快速,还提高了游客的体验感觉。所以从实用方面也是可行的。
前台分为未注册和已注册两种服务需求。
未注册用户:
注册账号:用户填写个人信息并进行验证。
浏览景点:用户可以从景点分类中查看某个景点的信息如"名称,特点,景点地区,票价,其他用户的评论"。
已注册用户:
登录:用户输入账号及密码进行登录。
修改个人信息:用户进入个人信息面板可对信息进行修改。
点击评论:用户点击评论可查看其他用户对该景点的评价。
购票:用户点进购票页面,根据自己的需求可以去购买相应的票据。
评论:用户可以经过自己的感受对景点做出评论
景点资讯:用户登录后可以查看系统中最新的资讯。
景点信息:用户可以根据需求点击相应的景点浏览信息。
推荐:用户在浏览景点后在此基础上推荐类似的景点,形成推荐列表,提供给用户更好的购票等,还能购票删除记录。
3.3.2 后台管理员功能
登陆密码修改:管理员可以修改自己的登录密码,保障系统的安全性。
处理购票单:管理员可以查看购票单信息。
景点信息管理:管理员可以对景点信息进行增加,修改,删除,维护。
景点分类管理:管理员可以对景点分类进行增加,修改,删除,维护。
评论管理:管理员可以查看用户评论,给出建议,还可以删除评论。
用户管理:管理员可以管理用户并查看用户信息。
核心算法代码分享如下:
python
import csv
import time
import requests
from DrissionPage import ChromiumPage
from DrissionPage.common import ActionChains
# 创建页面对象,并启动或接管浏览器
page = ChromiumPage()
import re
import pymysql
#area_list = ['北京','天津','上海','重庆','河北','山西','辽宁','吉林','黑龙江','江苏','浙江','安徽','福建','江西','山东','河南','湖北','湖南','广东','海南','四川','贵州','云南','陕西','甘肃','青海','台湾','内蒙','广西','西藏','宁夏','新疆']
area_list = ['云南',]
zxs=['北京','天津','上海','重庆']
# 数据库配置信息
host = "localhost"
port = 3306
user = "root"
password = "123456"
database = "tour"
# 连接mysql
conn = pymysql.connect(host=host, port=port, user=user, password=password, database=database)
cursor = conn.cursor()
def existsTour(name):
sql="select count(*) from tb_tour where name='%s'"
connect = None
connect = pymysql.connect(host="localhost", port=3306, user="root",
password="123456", database="tour")
cur = connect.cursor()
print(sql % name)
cur.execute(sql % name)
exist_count = cur.fetchmany(1)
if exist_count[0][0] > 0:
return 1
else:
return 0
def address2(address):
url="xxxxxxxxxxxxxxxx"%('f1063cfc84a84bd3b1d3a339c87b8bd0',address)
data=requests.get(url)
contest=data.json()
#返回经度和纬度
print(contest)
contest=contest['geocodes'][0]
print(contest)
return contest
for area in area_list:
#url="xxxxxxxxxxxxxxxx"
url="xxxxxxxxxxxxxxxx"
req_urk=url % area
# 跳转到登录页面
page.get(req_urk)
# 换成景点门票
ele = page.ele('xpath://ul[@class="search_type_tab"]//li[@data-type="TICKET"]')
ele.click()
ele = page.ele('xpath://input[@class="lv_search w_380"]')
# 输入对文本框输入账号
ele.input(area)
# 点击登录按钮
page.ele('xpath://span[@class="btn_lv_search"]').click()
#time.sleep(3)
ac = ActionChains(page)
# for s in range(1, 10):
# # print(name)
# ac = ac.scroll(delta_y=20000)
#总页码
#page.run_js("window.scrollTo(0, document.body.scrollHeight)")
#time.sleep(10)
pages=int(page.ele('xpath://div[@class="pagebox"]/a[last()-1]/text()'))
pages=int(pages)
for p in range(0,pages):
#cp=page.ele('xpath://div[@class="pagebox"]/a[@class="nextpage"]')
#cp.click()
# 滑动到底部
cp_url="xxxxxxxxxxxxxxxx"+str(p+1)+"?keyword="+area+"&tabType=ticket#list"
page.get(cp_url)
#开始取值
tours=page.eles('xpath://div[@class="product-regular clearfix"]')
for tour in tours:
#景点名称必然能取到并且不报错
name=tour.ele('xpath://div[@class="product-section"]/h3[@class="product-ticket-title"]/a/text()')
if existsTour(name) == 1:
print('景点',name,'存在,无需反复爬取!')
continue
try:
AAAAA_Str=tour.ele('xpath://span[@class="level"]/text()').strip()
grade=str(len(AAAAA_Str))+'A'
except :
grade='0A'
try:
address=tour.ele('xpath://dl[1]/dd/@title').strip()
except:
address = name
try:
intro=tour.ele('xpath://dl[4]/dd/div').raw_text.strip()
except:
intro='暂无'
try:
#异常说明也没评论数据
hot=tour.ele('xpath://ul[@class="product-number"]/li[1]/b/text()').strip()
except:
hot=0
#评分
score=hot
# 评论数 评分连接
try:
# 异常说明也没评论数据
c_str = tour.ele('xpath://ul[@class="product-number"]/li[2]/a/text()').strip()
result = re.findall("\d+", c_str)
comments = result[0]
comments_url=tour.ele('xpath://ul[@class="product-number"]/li[2]/a/@href').strip()
except:
comments = 0
comments_url='暂无'
price =tour.ele('xpath://div[@class="product-price"]/em/text()').strip()
try:
#异常说明也没售出数据
sold_str=tour.ele('xpath://ul[@class="product-number"]/li[2]/a/text()').strip()
result = re.findall("\d+", sold_str)
msold =result[0]
except:
msold=0
#lng lat调用工具
print('#正在调用高德地图API获取经纬度===================================================')
try:
resp_add=address2(address)
print('高德返回结果',resp_add)
#lng=resp_add.split(',')[0] #经度
#lat=resp_add.split(',')[1] #纬度
lng = resp_add['location'].split(',')[0] # 经度
lat = resp_add['location'].split(',')[1] # 纬度
except:
lng='102.712251'
lat='25.040609'
#district = resp_add['district'] # 纬度
print('经度',lng,'纬度',lat)
print('#正在调用高德地图API获取经纬度===================================================')
img=tour.ele('xpath://img/@src').strip()
province_city = tour.ele('xpath://span[@class="city"]/text()').strip()
province_city = province_city.replace('[', '')
province_city = province_city.replace(']', '')
province_city_arr = province_city.split('·')
city_ = province_city_arr[0]
if city_ in zxs:
province = ''
city = province_city_arr[0]
district = province_city_arr[1]
else:
province = province_city_arr[0]
city = province_city_arr[1]
district = district = resp_add['district'] #从高德地图取
sql = "replace into tb_tour (name,grade,address,intro,hot,price,msold,lng,lat,img,province,city,district) " \
"values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
#data = (name, grade, address, intro, hot, price, msold, lng, lat, img, province, city, district,comments,comments_url)
data = (name, grade, address, intro, hot, price, msold, lng, lat, img, province, city, district)
print(name, grade, address, intro, hot, price, msold, lng, lat, img, province, city, district,comments,comments_url)
try:
cursor.execute(sql, data)
except:
print('sql出错',sql%(name, grade, address, intro, hot, price, msold, lng, lat, img, province, city, district))
continue
#cursor.execute(sql, data)
conn.commit()
########向景点csv写内容
tours_file = open("tours.csv", mode="a+", newline='', encoding="utf-8")
tours_writer = csv.writer(tours_file)
address = address.strip().replace(',', ',').replace('"', '').replace("'", '').replace("\n", '').replace('\r','').replace( '\t', '')
intro = intro.strip().replace(',', ',').replace('"', '').replace("'", '').replace("\n", '').replace('\r','').replace( '\t', '')
name = name.strip().replace(',', ',').replace('"', '').replace("'", '').replace("\n", '').replace('\r','').replace( '\t', '')
tours_writer.writerow(
[name, grade, address, intro, hot, price, msold, lng, lat, img, province, city, district,comments,comments_url])
tours_file.close()