1、项目介绍

技术栈
Python 作为主要开发语言,MySQL 作为数据存储数据库,Django 作为后端 Web 框架,selenium 用于携程网旅游数据的爬取采集,HTML 用于前端页面展示。

功能模块
· 旅游景点信息采集模块
· 注册登录模块
· 系统数据概况模块
· 数据可视化大屏模块
· 景区级别扇形图分析模块
· 评论排名模块
· 热门景区模块
· 景点评分排名模块
· 景区热度词云分析模块
· 后台管理模块

项目介绍
本系统是基于 Python 开发的旅游景点信息采集分析与可视化平台。系统利用 selenium 爬虫框架对携程网旅游数据进行自动化采集,获取景区名称、等级、评分、热度、评论数等关键信息,并将数据存储于 MySQL 数据库。后端采用 Django 框架实现业务逻辑处理与系统搭建,前端通过 HTML 页面完成数据可视化展示。平台涵盖数据采集、用户注册登录、后台数据管理以及多个可视化分析模块,能够以地图、词云、条形图、扇形图等多种形式呈现景区等级分布、热度指数、评论排名、评分排行等分析结果,为用户提供直观的旅游数据查询与分析工具,辅助快速掌握旅游市场概况。

2、项目界面

(1)旅游可视化大屏
该页面是旅游数据可视化大屏的核心展示页,可实时展示时间信息,能可视化呈现景区等级分布、景区人次和热度指数排名、全国旅游景点分布,还可展示景区热度和评分的关联关系、旅游景点相关词云图,整体通过多维度可视化图表和地图直观呈现各类旅游相关数据。

在这里插入图片描述

(2)系统首页—数据概况
该页面是旅游景点信息可视化系统的主界面,设有数据可视化大屏和后台管理入口,支持系统退出操作,可展示旅游景点数据总量、不同级别景区数量及景区级别扇形图、景区地域分布,还能呈现评论、热门、评分相关的景区排名和景区热度词云,也可通过中国地图查看景区相关分布信息。

在这里插入图片描述

(3)词云图分析
该页面是旅游景点信息可视化系统的核心数据展示页,设有数据可视化大屏和后台管理入口并支持退出系统,顶部有各类数据展示板块的导航入口,可直观呈现景区级别扇形图、评论最多、热门、评分最高的景区各类排名数据以及景区热度词云,整体实现旅游景点多维度数据的分类可视化展示与快速板块切换查看。

在这里插入图片描述

(4)评论前5景区
该页面是旅游景点信息可视化系统的评论最多景区展示页,设有数据可视化大屏和后台管理入口且支持退出系统,顶部有各数据板块的切换导航,可专门展示评论最多景区的TOP5相关数据,同时可快速切换查看景区级别扇形图、热门景区TOP5等其他旅游景点相关可视化数据板块,实现各维度景区数据的便捷切换与针对性展示。

在这里插入图片描述

(5)热门景区前5
该页面是旅游景点信息可视化系统的热门景区展示页,设有数据可视化大屏和后台管理入口且支持退出系统,顶部配备各数据板块的切换导航,可专门展示热门景区TOP5的相关数据,同时能快速切换查看景区级别扇形图、评论最多TOP5等其他旅游景点可视化数据板块,实现各维度景区数据的便捷切换与针对性展示。

在这里插入图片描述

(6)评分前10的景区
该页面是旅游景点信息可视化系统的评分最高景区展示页,设有数据可视化大屏和后台管理入口且支持退出系统,顶部有各数据板块的切换导航,可专门展示评分最高景区TOP15的相关数据,同时能快速切换查看景区级别扇形图、评论最多TOP5等其他旅游景点可视化数据板块,实现各维度景区数据的便捷切换与针对性展示。

在这里插入图片描述

(7)景区评分扇形图
该页面是旅游景点信息可视化系统的景区级别扇形图展示页,设有数据可视化大屏和后台管理入口且支持退出系统,顶部有各数据板块的切换导航,可通过扇形图直观展示不同等级景区的分布占比及对应数量信息,同时能快速切换至评论最多TOP5、热门景区TOP5等其他旅游景点数据展示板块,实现各维度景区数据的便捷切换与可视化呈现。

在这里插入图片描述

(8)后台数据管理
该页面是旅游景点信息可视化系统的后台旅游数据编辑页,基于Django管理框架搭建,支持管理员对单条景区数据进行各项信息的修改编辑,可执行增加数据、删除数据的操作,提供多种保存操作的选项,还能查看数据修改历史,同时可对用户、组相关信息进行管理,兼顾景区数据的增删改查及基础权限管理功能。

在这里插入图片描述

(9)数据爬取
该页面是旅游景点信息可视化系统的爬虫开发调试界面,基于Python开发环境搭建,可编写和运行旅游数据爬虫代码,实现指定旅游平台景点信息的定向爬取,能读取URL列表文件并处理链接,配置浏览器爬取参数,终端实时展示爬取进度与目标链接,同时支持代码备份、文件管理和项目相关脚本的运行调试。

在这里插入图片描述

3、项目说明

一、技术栈简要说明
系统后端采用 Python 语言与 Django 框架构建,数据库选用 MySQL 进行数据存储。数据采集环节基于 selenium 爬虫框架对携程网旅游数据进行自动化抓取,获取景区名称、等级、评分、热度、评论数等关键信息。前端页面使用 HTML 进行结构搭建,可视化部分结合 Echarts 图表库实现多种数据图表的渲染展示。

二、功能模块详细介绍
· 旅游景点信息采集模块
基于 selenium 爬虫框架,在 Python 开发环境中编写爬虫代码,实现携程网旅游景点信息的定向抓取,可读取 URL 列表、配置浏览器爬取参数,终端实时展示爬取进度与目标链接,获取景区名称、等级、评分、热度、评论数等数据后存入 MySQL 数据库。

· 注册登录模块
提供用户注册与登录功能,实现身份验证与权限管控,用户通过验证后可进入系统访问各类旅游数据可视化分析模块,保障系统访问安全。

· 系统数据概况模块
作为系统主界面,展示旅游景点数据总量、不同级别景区数量及景区级别扇形图、景区地域分布等核心统计信息,为用户提供初始数据认知。

· 数据可视化大屏模块
以综合大屏形式集中展示旅游核心数据,包含时间信息、景区等级分布、景区人次和热度指数排名、全国旅游景点分布地图、景区热度与评分关联分析、旅游景点相关词云图等,实现多维度可视化图表联动展示。

· 景区级别扇形图分析模块
通过扇形图直观呈现不同等级景区的分布占比及对应数量信息,帮助用户快速了解景区等级结构与分布特征。

· 评论排名模块
以排行榜形式展示评论数量最多的景区 TOP5 或 TOP15 排名数据,突出呈现用户参与度较高的热门景区,便于用户快速发现高关注度景点。

· 热门景区模块
以排行榜形式展示热度指数最高的景区 TOP5 相关数据,反映景区的受欢迎程度与市场热度,为用户出行选择提供参考。

· 景点评分排名模块
以排行榜形式展示评分最高的景区 TOP15 排名数据,呈现用户评价较高的优质景点,辅助用户进行旅游决策。

· 景区热度词云分析模块
通过词云图展示旅游景点相关关键词的分布情况,直观呈现景区评论中的高频词汇与热点主题,帮助用户快速捕捉景区特色。

· 后台管理模块
基于 Django 管理框架搭建,支持管理员对景区数据进行增删改查操作,可编辑单条景区各项信息、增加数据、删除数据、查看数据修改历史,同时可对用户及组相关信息进行管理,兼顾景区数据维护与基础权限管理功能。

三、项目总结
本系统是基于 Python 与 Django 开发的旅游景点信息采集分析与可视化平台,构建了从数据采集到可视化展示的全流程解决方案。系统利用 selenium 爬虫框架对携程网旅游数据进行自动化抓取,获取景区名称、等级、评分、热度、评论数等关键信息并存储于 MySQL 数据库。平台涵盖数据概况概览、可视化大屏、景区级别扇形图、评论排名、热门景区、评分排名、热度词云分析等多个可视化模块,能够以地图、词云、条形图、扇形图、排行榜等多种形式呈现景区等级分布、热度指数、评论排名、评分排行等分析结果。后台管理模块支持景区数据的增删改查与权限管理,为用户提供直观的旅游数据查询与分析工具,辅助快速掌握旅游市场概况。

4、核心代码


def login(request):
    """登录函数"""
    if request.method == "POST":
        user = request.POST.get('user')
        pass_word = request.POST.get('password')
        print('user------>', user)
        users_list = list(models.UserList.objects.all().values("user_id"))
        users_id = [x['user_id'] for x in users_list]
        print(users_id)
        # print(students_num)
        ret = models.UserList.objects.filter(user_id=user, pass_word=pass_word)
        if user not in users_id:
            return JsonResponse({'code': 1, 'msg': '该账号不存在!'})
        elif ret:
            # 有此用户 -->> 跳转到首页
            # 登录成功后,将用户名和昵称保存到session 中,
            request.session['user_id'] = user
            user_obj = ret.last()
            user_name = user_obj.user_name
            request.session['user_name'] = user_name
            return JsonResponse({'code': 0, 'msg': '登录成功!'})
        else:
            return JsonResponse({'code': 1, 'msg': '密码错误!'})
    else:
        return render(request, "login.html")


def register(request):
    """注册函数"""
    if request.method == "POST":
        user = request.POST.get('user')
        pass_word = request.POST.get('password')
        user_name = request.POST.get('user_name')
        users_list = list(models.UserList.objects.all().values("user_id"))
        users_id = [x['user_id'] for x in users_list]
        if user in users_id:
            return JsonResponse({'code': 1, 'msg': '该账号已存在!'})
        else:
            models.UserList.objects.create(user_id=user, user_name=user_name, pass_word=pass_word)
            request.session['user_id'] = user  # 设置缓存
            request.session['user_name'] = user_name
            return JsonResponse({'code': 0, 'msg': '注册成功!'})
    else:
        return render(request, "register.html")


# 退出(登出)
def logout(request):
    # 1. 将session中的用户名、昵称删除
    request.session.flush()
    # 2. 重定向到 登录界面
    return redirect('login')


def index(request):
    return render(request, "index.html", locals())


def get_screen(request):
    # city_list = ['金安区', '裕安区', '叶集区', '霍邱县', '舒城县', '金寨县', '霍山县']
    # city_list = ['荔湾区', '越秀区', '海珠区', '天河区', '白云区', '黄埔区', '番禺区', '花都区', '南沙区', '从化区', '增城区']
    city_list = ['北京市', '天津市', '河北省', '山西省', '内蒙古自治区', '辽宁省', '吉林省', '黑龙江省', '上海市', '江苏省',
     '浙江省', '安徽省', '福建省', '江西省', '山东省', '河南省', '湖北省', '湖南省', '广东省', '广西壮族自治区',
     '海南省', '重庆市', '四川省', '贵州省', '云南省', '西藏自治区', '陕西省', '甘肃省', '青海省', '宁夏回族自治区',
     '新疆维吾尔自治区', '台湾省', '香港特别行政区', '澳门特别行政区', '']


    # 等级占比图
    level_list = list(set([x[0] for x in list(models.Data.objects.all().values_list('level'))]))
    l_1_data = []
    for level in level_list:
        l_1_data.append({'name': level, "value": models.Data.objects.filter(level=level).count()})
    # print(l_1_data)

    # 散点图
    hot_score = list(models.Data.objects.all().values_list('hot', 'score'))
    hot_score = [[float(x[0]), float(x[1])] for x in hot_score if x[1] != '0']
    hot_score = sorted(hot_score, key=lambda x: x[0])
    # print(hot_score)

    # 处理中间柱形图数据
    c_1_data = list(models.Data.objects.all().values_list('name', 'hot').distinct().order_by('-hot'))[0:10]
    # print(c_1_data)
    c_1_x = [x[0] for x in c_1_data]
    c_1_y = [float(x[1]) for x in c_1_data]

    #  处理地图数据
    map_data = []
    for x in city_list:
        map_data.append({'name': x, 'value': models.Data.objects.filter(address__icontains=x[0:2]).count()})
    print("map_data------>", map_data)

    # 评分排行
    comment_list = list(models.Data.objects.all().values_list('name', 'comment_count').distinct())
    # print(comment_list)
    comment_list = [[x[0], int(x[1].replace('条点评', ''))] for x in comment_list]
    comment_list = sorted(comment_list, key=lambda x: x[1], reverse=True)[0:10]
    r_1_x = [x[0] for x in comment_list]
    r_1_y = [float(x[1]) for x in comment_list]

    # 词云图
    r_2_data = list(models.Data.objects.all().values_list('name', 'comment_count').distinct())
    # print(comment_list)
    r_2_data = [[x[0], int(x[1].replace('条点评', ''))] for x in r_2_data]
    r_2_data = [{"name": x[0], "value": x[1]} for x in r_2_data]

    return render(request, "screen.html", locals())


def welcome(request):
    """此函数用于处理控制台页面"""
    all_data = models.Data.objects.all().count()
    data_5a = models.Data.objects.filter(Q(level__icontains='5A') | Q(name__icontains='5A')).count()
    data_4a = models.Data.objects.filter(Q(level__icontains='4A') | Q(name__icontains='4A')).count()
    hot_data = [[x[0], float(x[1])] for x in list(models.Data.objects.all().values_list('name', 'hot').distinct())]
    hot_data = sorted(hot_data, key=lambda x: x[1], reverse=True)[0]
    hot_data_name = hot_data[0]
    hot_data_hot = hot_data[1]

    # city_list = ['金安区', '裕安区', '叶集区', '霍邱县', '舒城县', '金寨县', '霍山县']
    # city_list = ['荔湾区', '越秀区', '海珠区', '天河区', '白云区', '黄埔区', '番禺区', '花都区', '南沙区', '从化区', '增城区']
    city_list = ['北京市', '天津市', '河北省', '山西省', '内蒙古自治区', '辽宁省', '吉林省', '黑龙江省', '上海市',
                 '江苏省',
                 '浙江省', '安徽省', '福建省', '江西省', '山东省', '河南省', '湖北省', '湖南省', '广东省',
                 '广西壮族自治区',
                 '海南省', '重庆市', '四川省', '贵州省', '云南省', '西藏自治区', '陕西省', '甘肃省', '青海省',
                 '宁夏回族自治区',
                 '新疆维吾尔自治区', '台湾省', '香港特别行政区', '澳门特别行政区', '']

    #  处理地图数据
    map_data = []
    for x in city_list:
        map_data.append({'name': x, 'value': models.Data.objects.filter(address__icontains=x[0:2]).count()})
    # print(map_data)

    return render(request, "welcome.html", locals())


def chart_1(request):
    level_list = list(set([x[0] for x in list(models.Data.objects.all().values_list('level'))]))
    l_1_data = []
    all_value = 0
    for level in level_list:
        a = models.Data.objects.filter(level=level).count()
        all_value += a
        l_1_data.append({'name': level, "value": a})

    # print(l_1_data)
    return render(request, "echarts_1.html", locals())


def chart_2(request):
    comment_list = list(models.Data.objects.all().values_list('name', 'comment_count').distinct())
    # print(comment_list)
    comment_list = [[x[0], int(x[1].replace('条点评', ''))] for x in comment_list]
    comment_list = sorted(comment_list, key=lambda x: x[1], reverse=True)[0:5]
    c_1_data = [{'name': x[0], 'value': x[1]} for x in comment_list]
    le_data = [x[0] for x in comment_list]
    return render(request, "echarts_2.html", locals())


def chart_3(request):
    comment_list = list(models.Data.objects.all().values_list('name', 'hot').distinct())
    # print(comment_list)
    comment_list = [[x[0], float(x[1].replace('条点评', ''))] for x in comment_list]
    comment_list = sorted(comment_list, key=lambda x: x[1], reverse=True)[0:5]
    c_1_data = [{'name': x[0], 'value': x[1]} for x in comment_list]
    le_data = [x[0] for x in comment_list]
    return render(request, "echarts_3.html", locals())


def chart_4(request):
    comment_list = list(models.Data.objects.all().values_list('name', 'score').distinct())
    # print(comment_list)
    comment_list = [[x[0], float(x[1].replace('条点评', ''))] for x in comment_list]
    comment_list = sorted(comment_list, key=lambda x: x[1], reverse=True)[0:15]
    c_1_data = [{'name': x[0], 'value': x[1]} for x in comment_list]
    le_data = [x[0] for x in comment_list]
    return render(request, "echarts_4.html", locals())


def chart_5(request):
    # 词云图
    r_2_data = list(models.Data.objects.all().values_list('name', 'comment_count').distinct())
    # print(comment_list)
    r_2_data = [[x[0], int(x[1].replace('条点评', ''))] for x in r_2_data]
    r_2_data = [{"name": x[0], "value": x[1]} for x in r_2_data]
    return render(request, "echarts_5.html", locals())

更多推荐