欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > 分享一个基于Python的广东热门旅游数据可视化分析系统flask毕设(源码、调试、LW、开题、PPT)

分享一个基于Python的广东热门旅游数据可视化分析系统flask毕设(源码、调试、LW、开题、PPT)

2024/11/29 21:18:58 来源:https://blog.csdn.net/m0_72599287/article/details/141560109  浏览:    关键词:分享一个基于Python的广东热门旅游数据可视化分析系统flask毕设(源码、调试、LW、开题、PPT)

💕💕作者:计算机源码社
💕💕个人简介:本人 八年开发经验,擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等,大家有这一块的问题可以一起交流!
💕💕学习资料、程序开发、技术解答、文档报告
💕💕如需要源码,可以扫取文章下方二维码联系咨询

💕💕Java项目
💕💕微信小程序项目
💕💕Android项目
💕💕Python项目
💕💕PHP项目
💕💕ASP.NET项目
💕💕Node.js项目
💕💕选题推荐

项目实战|基于Python的广东热门旅游数据可视化分析系统

文章目录

  • 1、选题背景
  • 2、研究目的和意义
  • 3、系统研究内容
  • 4、系统页面设计
  • 5、参考文献
  • 6、核心代码

1、选题背景

  随着旅游业的快速发展和互联网技术的普及,越来越多的游客依赖于在线旅游平台获取旅游信息和规划行程。广东作为中国的旅游大省,拥有丰富的旅游资源和众多热门景点。然而,海量的旅游数据分布在各大网站上,缺乏系统性和直观的展示方式,难以为游客提供高效、全面的信息支持。因此,开发一个基于Python的广东热门旅游数据可视化分析系统,通过爬虫技术获取并分析旅游数据,能够为用户提供直观的视觉化分析和数据展示,帮助用户更好地了解和选择旅游目的地。

2、研究目的和意义

  本系统的开发旨在通过爬虫技术自动获取广东热门旅游景点的相关数据,并通过数据清洗、处理,将这些数据进行系统化存储与管理。进一步通过数据可视化技术,将复杂的旅游信息以更加直观的方式呈现出来,帮助用户快速了解旅游景点的各类指标,如景点热度、评分、评论数量等。系统还提供用户注册、登录、个人信息管理以及景点信息管理等功能,旨在为用户和管理者提供一个全面、高效的旅游数据管理与分析平台。

  基于Python的广东热门旅游数据可视化分析系统不仅能够提升旅游信息的获取与处理效率,还能通过可视化手段,增强数据的可读性和易用性,助力决策过程。对于游客而言,系统所提供的各类数据分析和展示,能够为其旅游决策提供科学的参考,节省时间和精力。对于旅游管理者和研究者而言,系统则可以作为数据分析的有力工具,通过分析热门景点的热度、评价等信息,帮助优化旅游资源配置,提高旅游服务质量,同时也为未来的旅游市场发展策略提供数据支持。

3、系统研究内容

本课题旨在设计与实现一个基于Python的广东热门旅游数据可视化分析系统,通过多种技术手段对广东热门旅游景点数据进行采集、处理、存储及可视化展示。具体研究内容包括以下几个方面:

本课题采用Scrapy爬虫技术,从携程网站中自动化地抓取广东省热门旅游景点的相关数据。这些数据包括景点名称、景点热度、评分、评论数量等重要指标。通过构建高效的爬虫脚本,确保数据采集的全面性与准确性。

本课题对获取的数据进行处理与清洗,包括去除重复数据、处理缺失值及规范化数据格式等,以提高数据的质量和一致性。此过程确保了后续数据存储与分析的可靠性。清洗后的数据被存储到MySQL数据库中,便于后续的数据管理与调用。

接下来本课题使用Echarts可视化框架进行数据的展示与分析。系统通过大屏可视化分析,直观地展示广东热门旅游景点的相关信息。具体展示内容包括景点名称的词云图、景点热度可视化、评分可视化、评论数量可视化、景点总数统计等。这些可视化结果不仅有助于用户了解各景点的受欢迎程度和用户反馈,还能为旅游相关的市场分析和决策提供数据支持。

最后本课题开发了一个基于Python和Flask框架的Web网站,提供用户注册、登录、个人信息管理、景点信息管理和系统公告管理等功能。用户可以通过该网站查看上述可视化结果,管理自己的账户信息,并获得系统公告和通知。该系统为用户提供了一个集成化的旅游数据分析与管理平台,实现了数据采集、处理、存储、分析与展示的全过程。

4、系统页面设计

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

如需要源码,可以扫取文章下方二维码联系咨询

5、参考文献

[1]刘燕楠.基于爬虫技术对云冈石窟景区评论的情感分析与可视化展示[J].电脑知识与技术,2024,20(21):74-76.DOI:10.14004/j.cnki.ckt.2024.1082.
[2]张名扬,王子俊,罗兴稳,等.基于协同过滤算法的旅游景点可视化分析系统的设计与实现[J].长江信息通信,2024,37(07):21-23.DOI:10.20153/j.issn.2096-9759.2024.07.007.
[3]南方.江西省数字文化服务平台底层支撑系统的建设与应用[J].广播电视网络,2024,31(06):92-96.DOI:10.16045/j.cnki.catvtec.2024.06.021.
[4]陈文婷,沈丽珍,汪侠.旅游信息流对假期客流的时空影响效应研究——以淄博市为例[J].地理科学进展,2024,43(06):1156-1166.
[5]简易,林岩,张书涵.基于POI数据的徐州市旅游景点空间分布特征及影响因素研究[J].智能建筑与智慧城市,2024,(06):36-39.DOI:10.13655/j.cnki.ibci.2024.06.010.
[6]王馨梓,李鹏,马楠.GIS在旅游业的应用现状与建模方法[J].绿色科技,2024,26(11):205-211.DOI:10.16663/j.cnki.lskj.2024.11.024.
[7]陈成伟,陆福运.基于虚幻引擎的交旅融合服务区可视化系统技术与实现[J].大众科技,2024,26(03):21-24.
[8]孟文杰,孙晓瑜,王政凯,等.数智化背景下山东文旅数据中台设计[J].无线互联科技,2024,21(10):93-95.
[9]徐春,王萌萌,孙彬.融合知识图谱和图注意力网络的旅游推荐算法[J].计算机工程与设计,2024,45(05):1420-1427.DOI:10.16208/j.issn1000-7024.2024.05.019.
[10]彭珺.基于事理图谱的网络游记文本知识融合研究[D].吉林大学,2024. DOI:10.27162/d.cnki.gjlin.2024.000344.
[11]李卫帆,刘晓静,毛磊,等.数据赋能特色旅游终端卷烟营销能力分析[J].财经界,2024,(13):57-59.DOI:10.19887/j.cnki.cn11-4098/f.2024.13.053.
[12]李斌,陈琳敏,张晓芳,等.旅游资源普查GIS空间数据库设计与实现[J].延安职业技术学院学报,2024,38(02):99-104.DOI:10.13775/j.cnki.cn61-1472/g4.2024.02.016.
[13]黄玉亭.数字化转型背景下旅游服务企业财务预决算模型的创新[J].金融客,2024,(04):36-38.
[14]孙雨露,路菁,姚铮.数字文旅视域下移动智慧旅游平台拓展技术集成研究[J].无线互联科技,2024,21(07):46-49.
[15]贾衍菊,李思雨.基于公众参与地理信息系统的乡村旅游区主客依恋空间表征差异研究[J].干旱区资源与环境,2024,38(06):191-199.DOI:10.13448/j.cnki.jalre.2024.133.
[16]伍进,王颖,洪万杰.国内旅游业扩展现实技术应用研究综述[J].乐山师范学院学报,2024,39(03):59-70.DOI:10.16069/j.cnki.51-1610/g4.2024.03.009.
[17]黄正鹏,马欣,陈雪,等.基于线性回归算法对多彩贵州旅游数据的分析及应用[J].软件工程,2024,27(03):63-66.DOI:10.19644/j.cnki.issn2096-1472.2024.003.013.
[18]范帅超,李华.基于GIS的历史文化街区应急疏散能力可视化评估研究[J].中国安全生产科学技术,2024,20(02):28-34.
[19]曹许悦,孙永华,王衍昭,等.湿地数字孪生技术及其应用综述[J].测绘通报,2024,(02):32-38.DOI:10.13474/j.cnki.11-2246.2024.0206.
[20]丁宇阳,胡涵,王莹露,等.基于区块链技术的旅游服务及可视化分析系统设计[J].长江信息通信,2024,37(02):166-169.DOI:10.20153/j.issn.2096-9759.2024.02.050.

6、核心代码

# # -*- coding: utf-8 -*-# 数据爬取文件import scrapy
import pymysql
import pymssql
from ..items import GuangdongItem
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 GuangdongSpider(scrapy.Spider):name = 'guangdongSpider'spiderUrl = 'https://you.ctrip.com/sight/guangzhou152/s0-p{}.html;https://you.ctrip.com/sight/shenzhen26/s0-p{}.html;https://you.ctrip.com/sight/zhuhai27/s0-p{}.html;https://you.ctrip.com/sight/foshan207/s0-p{}.html;https://you.ctrip.com/sight/dongguan212/s0-p{}.html;https://you.ctrip.com/sight/shantou215/s0-p{}.html'start_urls = spiderUrl.split(";")protocol = ''hostname = ''realtime = Falseheaders = {"Cookie":"输入自己的cookie"}def __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, '1040ett3_guangdong') == 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,headers=self.headers,callback=self.parse)else:yield scrapy.Request(url=url,headers=self.headers,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, '1040ett3_guangdong') == 1:cursor.close()connect.close()self.temp_data()returnlist = response.css('div.list_wide_mod2 div.list_mod2')for item in list:fields = GuangdongItem()if '(.*?)' in '''div.rdetailbox dl dt a::text''':try:fields["title"] = str( re.findall(r'''div.rdetailbox dl dt a::text''', item.extract(), re.DOTALL)[0].strip())except:passelse:try:fields["title"] = str( self.remove_html(item.css('''div.rdetailbox dl dt a::text''').extract_first()))except:passif '(.*?)' in '''dd.ellipsis::text''':try:fields["address"] = str( re.findall(r'''dd.ellipsis::text''', item.extract(), re.DOTALL)[0].strip())except:passelse:try:fields["address"] = str( self.remove_html(item.css('''dd.ellipsis::text''').extract_first()))except:passif '(.*?)' in '''div.leftimg a img::attr(src)''':try:fields["pic"] = str( re.findall(r'''div.leftimg a img::attr(src)''', item.extract(), re.DOTALL)[0].strip())except:passelse:try:fields["pic"] = str( self.remove_html(item.css('''div.leftimg a img::attr(src)''').extract_first()))except:passif '(.*?)' in '''b.hot_score_number::text''':try:fields["hotnumber"] = float( re.findall(r'''b.hot_score_number::text''', item.extract(), re.DOTALL)[0].strip())except:passelse:try:fields["hotnumber"] = float( self.remove_html(item.css('b.hot_score_number::text').extract_first()))except:passif '(.*?)' in '''a.score strong::text''':try:fields["score"] = float( re.findall(r'''a.score strong::text''', item.extract(), re.DOTALL)[0].strip())except:passelse:try:fields["score"] = float( self.remove_html(item.css('a.score strong::text').extract_first()))except:passif '(.*?)' in '''a.recomment::text''':try:fields["commentcount"] = int( re.findall(r'''a.recomment::text''', item.extract(), re.DOTALL)[0].strip().replace("条点评)","").replace("(",""))except:passelse:try:fields["commentcount"] = int( self.remove_html(item.css('a.recomment::text').extract_first()).replace("条点评)","").replace("(",""))except:passif '(.*?)' in '''div.rdetailbox dl dt a::attr(href)''':try:fields["laiyuan"] = str( re.findall(r'''div.rdetailbox dl dt a::attr(href)''', item.extract(), re.DOTALL)[0].strip())except:passelse:try:fields["laiyuan"] = str( self.remove_html(item.css('''div.rdetailbox dl dt a::attr(href)''').extract_first()))except:passdetailUrlRule = item.css('div.rdetailbox dl dt a::attr(href)').extract_first()if self.protocol in detailUrlRule or detailUrlRule.startswith('http'):passelif detailUrlRule.startswith('//'):detailUrlRule = self.protocol + ':' + detailUrlRuleelif detailUrlRule.startswith('/'):detailUrlRule = self.protocol + '://' + self.hostname + detailUrlRuleelse:detailUrlRule = self.protocol + '://' + self.hostname + '/' + detailUrlRuleyield scrapy.Request(url=detailUrlRule, meta={'fields': fields}, headers=self.headers, callback=self.detail_parse, dont_filter=True)# 详情解析def detail_parse(self, response):fields = response.meta['fields']try:fields["opentime"] = str( response.xpath('''.//div[p[contains(text(),"开放时间")]]//p[@class="baseInfoText cursor openTimeText"]//text()''').extract()[0].strip().replace("${column.delimiter}","").replace(" ","").replace(";",""))except:passtry:fields["phone"] = str( response.xpath('''.//div[p[contains(text(),"官方电话")]]//p[@class="baseInfoText"]//text()''').extract()[0].strip())except:passtry:fields["info"] = str( response.xpath('''.//div[contains(text(),"介绍")]/following-sibling::*[contains(@class, "moduleContent")][1]//text()''').extract()[0].strip().replace(" ",""))except:passreturn fields# 数据清洗def pandas_filter(self):engine = create_engine('mysql+pymysql://root:123456@localhost/spider1040ett3?charset=UTF8MB4')df = pd.read_sql('select * from guangdong 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 `guangdong`(id,title,address,pic,hotnumber,score,commentcount,opentime,phone,info,laiyuan)selectid,title,address,pic,hotnumber,score,commentcount,opentime,phone,info,laiyuanfrom `1040ett3_guangdong`where(not exists (selectid,title,address,pic,hotnumber,score,commentcount,opentime,phone,info,laiyuanfrom `guangdong` where`guangdong`.id=`1040ett3_guangdong`.id))order by rand()limit 50;'''cursor.execute(sql)connect.commit()connect.close()

💕💕作者:计算机源码社
💕💕个人简介:本人 八年开发经验,擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等,大家有这一块的问题可以一起交流!
💕💕学习资料、程序开发、技术解答、文档报告
💕💕如需要源码,可以扫取文章下方二维码联系咨询

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com