Scrapy + Django爬虫可视化项目实战(一)

news2024/11/19 18:27:50

目录

一、项目介绍

(一) 项目背景

(二) 项目介绍

二、系统实现

(一) 爬虫

1. 实现步骤

一、爬取字段

二、分析页面

三、具体实现

2. 爬虫结果


系列文章

Python升级打怪—Django入门

Python升级打怪—Scrapy零基础小白入门

实现技术

  • Scrapy
  • Django
  • Echarts

一、项目介绍

(一) 项目背景

在信息技术高速发展的今天,数据已经成为决策的重要依据。旅游业作为服务性行业的重要支柱,其数据资源尤为丰富。去哪儿网作为中国领先的在线旅游平台,拥有大量的景点数据,这些数据对于分析旅游市场动态、游客行为以及景点管理策略等具有极高的价值。通过对去哪儿网景点数据的分析,我们可以了解游客的偏好、旅游市场的趋势以及景点的竞争力等信息。同时,数据可视化可以将复杂的数据信息以直观、易懂的方式呈现出来,有助于决策者更好地理解数据背后的含义

(二) 项目介绍

本项目采用Scray框架爬取去哪儿网的景点数据以及景点的评论数据,将爬取到的数据存储为csv,再通过Django Web框架技术将数据存储到Mysql,然后通过编写接口、分析数据,通过接口将数据返回前端,前端结合Echarts制作可视化表

二、系统实现

(一) 爬虫

爬取网址:去哪儿网

1. 实现步骤

一、爬取字段

本项目爬取的数据分为两部分:【景点数据、景点评论数据】,并将爬取的数据分别存入两个CSV文件中

景点字段

# 景点名称
name = scrapy.Field()
# 景点价格
price = scrapy.Field()
# 所属城市
province = scrapy.Field()
# 评级
star = scrapy.Field()
# 地址
address = scrapy.Field()
# 详情url
detail_url = scrapy.Field()
# 评论数
comment_total = scrapy.Field()
# 短评
short_intro = scrapy.Field()
# 详评
detail_intro = scrapy.Field()
# 封面
cover = scrapy.Field()
# 销售额
sale_count = scrapy.Field()
# 地区
districts = scrapy.Field()
# 评分
score = scrapy.Field()

景点评论字段

# 景点名称
travel_name = scrapy.Field()
# 内容
content = scrapy.Field()
# 评论时间
date = scrapy.Field()
二、分析页面

以地区为北京的景点为例子,搜索结果如下

景点数据

通过分析页面得出,景点数据是通过发送Ajax请求获得,那么我们就不用解析页面,可以直接通过请求获取景点数据即可

当然请求里的景点数据有些字段是没有的,需要我们进入到景点的详情页去爬取

第一个景点:故宫博物院详情页路由

故宫博物院门票,故宫博物院门票预订,故宫博物院门票价格,去哪儿网门票

第二个景点:八达岭长城详情页路由

八达岭长城门票,八达岭长城门票预订,八达岭长城门票价格,去哪儿网门票

通过对比路由地址得出

景点的详情页路由是由基本的路由地址加上景点Id拼接得出,那么在Ajax请求的景点数据字段就有景点id,
那么如果获取指定的景点详情地址,就可以通过拼接该景点id获得

进入到景点详情页,解析页面,获取景点的【评分、评论人数、评论数据

这里我们可以通过Xpath解析页面 ,获取景点的评分以及评论人数

景点评论

请求URL示例:https://piao.qunar.com/ticket/detailLight/sightCommentList.json?sightId=38170&index=2&page=2&pageSize=10&tagType=0

景点评论数据也是通过发送Ajax请求获取,但不同的是需要携带上景点的id,在这个景点的id不同于进入景点详情页的景点id,它是在景点详情页中的,在查看网页源代码中,我们也是可以找到这个id的,后面我们就可以通过页面解析得到这个id,再拼接请求地址就可以去获取景点评论数据了

三、具体实现

基础的项目搭建就不在赘述,如有不懂的请看系列文章

爬虫前必看

  1. 一定要设置休眠时间!!!这对网站和你都好
  2. 因为爬取的数据量很大,爬虫时间会很长,大家可以根据自己的需求合理改造,比如选择合适时间爬取、爬取少量城市或每个城市爬取1-2页数据等

问题一:爬取的数据(景点数据、评论数据)分开存储

可以通过scrapy框架提供的pipelines文件中解决,根据定义数据结构存储到指定文件中,还可以进行数据处理等等操作

问题二:爬取数据层层嵌套

通过前面的页面分析,我们所要爬取的数据层层嵌套,爬取起来比较麻烦,当然也是难不倒我们的

首先准备基础数据

name = "Quanar"
allowed_domains = ["piao.qunar.com"]
start_urls = ["https://piao.qunar.com/daytrip/list.htm"]

# 所要爬取景点的城市
province_list = ['北京', '天津', '河北', '山西', '内蒙古', '辽宁', '吉林', '黑龙江', '上海', '江苏',
                 '浙江', '安徽', '福建', '江西', '山东', '河南', '湖北', '湖南', '广东',
                 '广西', '海南', '重庆', '四川', '贵州', '云南', '西藏', '陕西', '甘肃',
                 '青海', '宁夏', '新疆', '台湾', '香港', '澳门']

# 城市景点列表的ajax请求网址:keyword:城市名称 page:第几页 sort:pp=》按人气排名
url = 'https://piao.qunar.com/ticket/list.json?keyword=%s&region=&from=mpl_search_suggest&page=%s&sort=pp'
# 景点url
travel_url = 'https://piao.qunar.com/ticket/detail_%s.html'
# 景点评论url
comment_url = 'https://piao.qunar.com/ticket/detailLight/sightCommentList.json?sightId=%s&index=1&page=%s&pageSize=10&tagType=0'

发起请求,获取指定城市的指定页的景点数据

def start_requests(self):
    # 遍历每个城市列表
    for index, province in enumerate(self.province_list, 1):
        # 每个城市爬取 多少页 数据
        for page in range(5):
            yield Request(url=(self.url % (province, page)), callback=self.parse_travel_list,
                          meta={"province": province})
            return

解析景点数据,拼接景点详情页地址,继续发起请求

# 解析单个城市里的多个景点数据
def parse_travel_list(self, response):
    # 城市名称
    province = response.meta['province']

    # 城市景点列表
    travel_list = response.json()['data']['sightList']
    for index, travel in enumerate(travel_list):
        try:
            travel_item = TravelItem()
            # 景点名称
            name = travel['sightName']
            print("正在爬取该页 %s 条数据,景点名称为:%s" % (str(index + 1), name))
            # 门票价格
            try:
                price = travel['qunarPrice']
            except:
                price = 0

            # 有点景点可能没有评等级,所以需要判断一下
            try:
                star = travel['star']
            except:
                star = '未评'
            # 详细地址
            address = travel['address']
            # 短评
            short_intro = travel['intro']
            # 封面
            cover = travel['sightImgURL']
            # 销售额
            sale_count = travel['saleCount']
            # 地区
            districts = travel['districts']

            # ======================================= 详情爬虫
            # 景点id
            sightId = travel['sightId']
            # 详情地址
            detail_url = self.travel_url % sightId

            travel_item['name'] = name
            travel_item['province'] = province
            travel_item['price'] = price
            travel_item['star'] = star
            travel_item['address'] = address
            travel_item['short_intro'] = short_intro
            travel_item['cover'] = cover
            travel_item['sale_count'] = sale_count
            travel_item['districts'] = districts
            travel_item['detail_url'] = detail_url

            # 生成新的Request,并传递给下一个解析函数
            yield scrapy.Request(detail_url, callback=self.parse_travel_details, meta={'travel_item': travel_item})
            return
        except:
            continue

解析页面,获取景点的评分以及评论人数、请求景点评论所需的id,拼接获取景点评论的url,继续发起请求

    # 解析单个景点里的详情
    def parse_travel_details(self, response):
        travel_item = response.meta['travel_item']
        name = travel_item['name']
        travel_detail_xpath = Selector(response)
        # 评论总数
        comment_total = travel_detail_xpath.xpath('//span[@class="mp-description-commentCount"]/a/text()')[
            0].get().replace(
            '条评论', '')
        # 详情介绍
        detail_intro = travel_detail_xpath.xpath('//div[@class="mp-charact-desc"]//p/text()').get()
        # 评分
        score = travel_detail_xpath.xpath("//span[@id='mp-description-commentscore']/span/text()").get()
        if not score:
            score = 0
        else:
            score = score[0]

        travel_item['comment_total'] = comment_total
        travel_item['detail_intro'] = detail_intro
        travel_item['score'] = score

        # print("爬取存储的travel_item:%s" % travel_item)
        yield travel_item
        # ======================================= 评论爬虫
        data_sight_id = travel_detail_xpath.xpath('//div[@class="mp-tickets-new"]/@data-sightid')[0].get()
        comment_url = self.comment_url % (data_sight_id, 1)
        # 生成新的Request,并传递给下一个解析函数
        yield scrapy.Request(comment_url, callback=self.parse_comments, meta={"name": name})

解析评论数据

# 解析单个景点里的评论
def parse_comments(self, response):
    try:
        print("正在爬取%s的评论数据" % response.meta['name'])
        comment_json = response.json()['data']['commentList']
        name = response.meta['name']
        for comment in comment_json:
            item = CommentItem()
            if comment['content'] != '用户未点评,系统默认好评。':
                item['travel_name'] = name
                item['content'] = str(comment['content'])
                item['date'] = comment['date']
                yield item
    except:
        return

2. 爬虫结果

整个爬虫代码结束,让我们看看爬取到结果

爬取1958个景点数据

每个景点对应评论6213

好的,爬虫部分实现,接下来就是项目可视化,请看

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

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

相关文章

物联网精密空调监控指标解读:松越_TCP7022EX_精密空调

监控易是一款专业的IT和物联网设备监控软件,能够实时监控各类IT资源和物联网设备的运行状态,确保系统的稳定运行。在物联网精密空调领域,监控易对松越_TCP7022EX_精密空调进行了全面的监控,以下是对其监控指标的详细解读。 监控指…

2. Class 文件的组成

16 进制打开class文件 可以通过Notepad下载一个HexEditor插件,下载好该插件后可以以16进制的方式打开class看,打开后我们可以看到如下所示的图片: class 文件的组成 class 文件的组成部分为:魔数,版本号,…

Springboot与SpringSecurity使用(1):介绍、登录验证

一、介绍 Spring 是非常流行和成功的 Java 应用开发框架,Spring Security 正是 Spring 家族中的成员。Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。Web 应用的安全性包括用户认证(Authentication&#xff09…

Linux网络:传输层协议TCP(三)滑动窗口及流量控制

目录 一、关于滑动窗口在TCP中的应用 1.1什么是滑动窗口,为什么要有滑动窗口 1.2滑动窗口的实现 1.3滑动窗口针对丢包重传的处理机制 二、流量控制 一、关于滑动窗口在TCP中的应用 1.1什么是滑动窗口,为什么要有滑动窗口 在上一篇博文中博主阐述了…

植物神经紊乱拜拜啦! 6招让你心情美美哒,放松到飞起~

Hey宝贝们,是不是有时候觉得心里的小宇宙🌌乱糟糟的,像是有一群小精灵🧚‍♀️在跳舞,却偏偏踩不到点上?没错,这可能就是植物神经紊乱在作祟啦!别怕,我这就给你支几招&am…

Nginx系列-12 Nginx使用Lua脚本进行JWT校验

背景 本文介绍Nginx中Lua模块使用方式,并结合案例进行介绍。案例介绍通过lua脚本提取HTTP请求头中的token字段,经过JWT校验并提取id和name信息,设置到http请求头中发向后段服务器。 默认情况下,Nginx自身不携带lua模块&#xff0…

Transformer中的Multi-head Attention机制解析——从单一到多元的关注效益最大化

Transformer中的Multi-head Attention机制解析——从单一到多元的关注效益最大化 Multi-head Attention的核心作用 组件/步骤描述多头注意力机制(Multi-head Attention)Transformer模型中的关键组件,用于处理序列数据功能允许模型同时关注到…

Vue2从基础到实战(指令篇)

Vue中的常用指令! 概念:指令(Directives)是 Vue 提供的带有 v- 前缀 的 特殊 标签属性。 vue 中的指令按照不同的用途可以分为如下 6 大类: 内容渲染指令(v-html、v-text) 条件渲染指令&…

昇思25天学习打卡营第1天|快速入门-构建基于MNIST数据集的手写数字识别模型

非常感谢华为昇思大模型平台和CSDN邀请体验昇思大模型!从今天起,我将以打卡的方式,结合原文搬运和个人思考,分享25天的学习内容与成果。为了提升文章质量和阅读体验,我会将思考部分放在最后,供大家探索讨论…

04 | 深入浅出索引(上)

此系列文章为极客时间课程《MySQL 实战 45 讲》的学习笔记! 索引的常见模型 可以提供查询效率的数据结构有很多,常见的有三种:哈希表、有序数组、搜索数。 哈希表是一种以 key-value 形式存储的数据结构。输入一个 key,通过固定…

Markdown使用~~pandoc插件安装

目录 1.两大秘密武器 2.vscode创作 3.Typora的安装 4.pandoc安装 4.1百度网盘 4.2按照说明安装 4.3到达github里面下载 4.4选择对应版本 4.5进入偏好设置 4.6对于导出的路径进行配置 5.Typora和vscode的对比 6.如何正确的学习这个Typora软件 7.一点相关的说明 1.两…

做一个能和你互动玩耍的智能机器人之三

内容节选自英特尔的开源项目openbot的body目录下diy下的readme,这是一个组装和连线方式的说明文档,接线需要配合firmware固件使用,固件代码的接线柱是对应的。 body目录内部十分丰富,主要介绍了这个项目的背景和硬件以及如何让他…

datawhale逻辑推理赛题01

跟着datawhale参加了逻辑推理赛题,这个是一个大模型比赛入门非常好的比赛,可以帮助我们更快的上手大模型相关的业务 我参加的是天池的这个比赛,跟着datawhale官方的baseline01已经上分0.6498,是一个非常好的开始 后续我讲继续跟着…

java项目中添加SDK项目作为依赖使用(无需上传Maven)

需求: 当需要多次调用某个函数或算法时,不想每次调用接口都自己编写,可以将该项目打包,以添加依赖的方式实现调用 适用于: 无需上线的项目,仅公司或团队内部使用的项目 操作步骤: 以下面这…

Linux---进程(2)

目录 查看进程 查看进程pid 系统目录查看 理解当前工作目录用途 fork创建进程 存在问题 问题解决 问题一 问题二 本文介绍进程标识符的相关知识以及创建子进程。 查看进程 指令就是可执行程序,每次运行时,都需要被加载到内存,运行…

动物之森-小红书2024笔试(codefun2000)

题目链接 动物之森-小红书2024笔试(codefun2000) 题目内容 塔子哥最近在玩一款叫做“动物之森”的四字开放游戏世界。由于塔子哥氪金了,所以他在游戏中拥有很多个宝箱,每个宝箱里都装着一些他收集的宝石。每一种类型的宝石都有不同的作用。 有一天&…

java--jvm虚拟机(都是要点)

请带着以下问题,学习并理解jvm 问题一: 为什么fullGC会对系统性能有影响?youngGC却几乎没有? 问题二: outofmemory是什么异常?什么时候会出现?如何处理? 问题三: 线程…

鸿蒙 HarmonyOS NEXT端云一体化开发-云函数篇

前言 TODO:新建项目和应用,开通云函数服务(AGC)端侧开发:Arkts界面开发云测开发:云函数、认证服务、云存储、云数据库 一、登录 地址:https://id1.cloud.huawei.com/CAS/portal/loginAuth.htm…

Nginx周末部署

背景 Nginx是本人学习的一类中间件,上次完成了vue的搭建,所以顺便把项目加入Nginx吧 1. 镜像拉取与测试 查询dockerHub,选择最新最稳定的版本 docker pull nginx:stable-perl 执行下载 docker run -d --name mynginx -p 8080:80 -v D:\IM…

【Kubernetes】配置管理(一):ConfigMap

配置管理(一):ConfigMap 1.配置管理2.使用 ConfigMap 管理 Pod 的配置信息2.1 创建 ConfigMap2.1.1 在命令行中通过指定 ConfigMap 的参数进行创建2.1.2 通过指定的配置文件创建 ConfigMap2.1.3 通过一个文件内的多个键值对创建 ConfigMap2.1…