当前位置:

首页 > 编程开发 > Python实现旅游景点信息采集、评论分析和可视化

Python实现旅游景点信息采集、评论分析和可视化

本文目录

    大家好,我是啃书君!正所谓:有朋自远方来,不亦乐乎?有朋友来找我们玩,是一件很快乐的事情,那么我们要尽地主之谊,好好带朋友去玩耍!那么问题来了,什么时候去哪里玩最好呢,哪里玩的地方最多呢?今天将手把手教你使用线程池爬取同程旅行的景点信息及评论数据并做词云、数据可视化!!!带你了解各个城市的游玩景点信息。在开始爬取数据之前,我们首先来了解一下线程。线程进程:进程是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。线程:是轻量级的进程,是程序执行的最小单元,是进程的一个执行路径。一个进程中至

    Python实现旅游景点信息采集、评论分析和可视化

    大家好,我是啃书君!

    正所谓:有朋自远方来,不亦乐乎?有朋友来找我们玩,是一件很快乐的事情,那么我们要尽地主之谊,好好带朋友去玩耍!那么问题来了,什么时候去哪里玩最好呢,哪里玩的地方最多呢?

    今天将手把手教你使用线程池爬取同程旅行的景点信息及评论数据并做词云、数据可视化!!!带你了解各个城市的游玩景点信息。

    在开始爬取数据之前,我们首先来了解一下线程。

    线程

    进程:进程是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。

    线程:是轻量级的进程,是程序执行的最小单元,是进程的一个执行路径。

    一个进程中至少有一个线程,进程中的多个线程共享进程的资源。

    线程生命周期

    在创建多线程之前,我们先来学习一下线程生命周期,如下图所示:

    Python实现旅游景点信息采集、评论分析和可视化

    由图可知,线程可以分为五个状态——新建、就绪、运行、阻塞、终止。

    首先新建一个线程并开启线程后线程进入就绪状态,就绪状态的线程不会马上运行,要获得CPU资源才会进入运行状态,在进入运行状态后,线程有可能会失去CPU资源或者遇到休眠、io操作(读写等操作)线程进入就绪状态或者阻塞状态,要等休眠、io操作结束或者重新获得CPU资源后,才会进入运行状态,等到运行完后进入终止状态。

    注意:新建线程系统是需要分配资源的,终止线程系统是需要回收资源的,那么如何减去新建/终止线程的系统开销呢,这时我们可以创建线程池来重用线程,这样就可以减少系统的开销了。

    在创建线程池之前,我们先来学习如何创建多线程。

    创建多线程

    创建多线程可以分为四步:

    1. 创建函数;
    2. 创建线程;
    3. 启动线程;
    4. 等待结束;

    创建函数

    为了方便演示,我们拿博客园的网页做爬虫函数,具体代码如下所示:

    import requests
    urls=[
     f'https://www.cnblogs.com/#p{page}'
     for page in range(1,50)
    ]
    def get_parse(url):
     response=requests.get(url)
    print(url,len(response.text))

    首先导入requests网络请求库,把我们所有的要爬取的URL保存在列表中,然后自定义函数get_parse来发送网络请求、打印请求的URL和响应的字符长度。

    创建线程

    在上一步我们创建了爬虫函数,接下来将创建线程了,具体代码如下所示:

    import threading
    #多线程
    def multi_thread():
     threads=[]
     for url in urls:
     threads.append(
     threading.Thread(target=get_parse,args=(url,))
     )

    首先我们导入threading模块,自定义multi_thread函数,再创建一个空列表threads来存放线程任务,通过threading.Thread()方法来创建线程。其中:

    • target为运行函数;
    • args为运行函数所需的参数。

    注意args中的参数要以元组的方式传入,然后通过.append()方法把线程添加到threads空列表中。

    启动线程

    线程已经创建好了,接下来将启动线程了,启动线程很简单,具体代码如下所示:

    for thread in threads:
     thread.start()

    首先我们通过for循环把threads列表中的线程任务获取下来,通过.start()来启动线程。

    等待结束

    启动线程后,接下来将等待线程结束,具体代码如下所示:

    for thread in threads:
     thread.join()

    和启动线程一样,先通过for循环把threads列表中的线程任务获取下来,再使用.join()方法等待线程结束。

    多线程已经创建好了,接下来将测试一下多线程的速度如何,具体代码如下所示:

    if __name__ == '__main__':
    t1=time.time()
     multi_thread()
     t2=time.time()
     print(t2-t1)

    运行结果如下图所示:

    Python实现旅游景点信息采集、评论分析和可视化

    多线程爬取50个博客园网页只要1秒多,而且多线程的发送网络请求的URL是随机的。

    我们来测试一下单线程的运行时间,具体代码如下所示:

    if __name__ == '__main__':
     t1=time.time()
     for i in urls:
     get_parse(i)
     t2=time.time()
     print(t2-t1)

    运行结果如下图所示:

    Python实现旅游景点信息采集、评论分析和可视化

    单线程爬取50个博客园网页用了9秒多,单线程的发送网络请求的URL是按顺序的。

    在上面我们说了,新建线程系统是需要分配资源的,终止线程系统是需要回收资源的,为了减少系统的开销,我们可以创建线程池。

    线程池原理

    一个线程池由两部分组成,如下图所示:

    Python实现旅游景点信息采集、评论分析和可视化

    • 线程池:里面提前建好N个线程,这些都会被重复利用;
    • 任务队列:当有新任务的时候,会把任务放在任务队列中。

    当任务队列里有任务时,线程池的线程会从任务队列中取出任务并执行,执行完任务后,线程会执行下一个任务,直到没有任务执行后,线程会回到线程池中等待任务。

    使用线程池可以处理突发性大量请求或需要大量线程完成任务(处理时间较短的任务)。

    好了,了解了线程池原理后,我们开始创建线程池。

    线程池创建

    Python提供了ThreadPoolExecutor类来创建线程池,其语法如下所示:

    ThreadPoolExecutor(max_workers=None, thread_name_prefix='', initializer=None, initargs=())

    其中:

    • max_workers:最大线程数;
    • thread_name_prefix:允许用户控制由线程池创建的threading.Thread工作线程名称以方便调试;
    • initializer:是在每个工作者线程开始处调用的一个可选可调用对象;
    • initargs:传递给初始化器的元组参数。

    注意:在启动 max_workers 个工作线程之前也会重用空闲的工作线程。

    在ThreadPoolExecutor类中提供了map()和submit()函数来插入任务队列。其中:

    map()函数

    map()语法格式为:

    map(调用方法,参数队列)

    具体示例如下所示:

    import requestsimport concurrent.futuresimport timeurls=[f'https://www.cnblogs.com/#p{page}'for page in range(1,50)]def get_parse(url):response=requests.get(url)return response.textdef map_pool():with concurrent.futures.ThreadPoolExecutor(max_workers=20) as pool:htmls=pool.map(get_parse,urls)htmls=list(zip(urls,htmls))for url,html in htmls:print(url,len(html))if __name__ == '__main__':t1=time.time()map_pool()t2=time.time()print(t2-t1)

    首先我们导入requests网络请求库、concurrent.futures模块,把所有的URL放在urls列表中,然后自定义get_parse()方法来返回网络请求返回的数据,再自定义map_pool()方法来创建代理池,其中代理池的最大max_workers为20,调用map()方法把网络请求任务放在任务队列中,在把返回的数据和URL合并为元组,并放在htmls列表中。

    运行结果如下图所示:

    Python实现旅游景点信息采集、评论分析和可视化

    可以发现map()函数返回的结果和传入的参数顺序是对应的。

    注意:当我们直接在自定义方法get_parse()中打印结果时,打印结果是乱序的。

    submit()函数

    submit()函数语法格式如下:

    submit(调用方法,参数)

    具体示例如下:

    def submit_pool():with concurrent.futures.ThreadPoolExecutor(max_workers=20)as pool:futuress=[pool.submit(get_parse,url)for url in urls]futures=zip(urls,futuress)for url,future in futures:print(url,len(future.result()))

    运行结果如下图所示:

    Python实现旅游景点信息采集、评论分析和可视化

    注意:submit()函数输出结果需需要调用result()方法。

    好了,线程知识就学到这里了,接下来开始我们的爬虫。

    爬前分析

    首先我们进入同程旅行的景点网页并打开开发者工具,如下图所示:

    Python实现旅游景点信息采集、评论分析和可视化

    经过寻找,我们发现各个景点的基础信息(详情页URL、景点id等)都存放在下图的URL链接中,

    Python实现旅游景点信息采集、评论分析和可视化

    其URL链接为:

    https://www.ly.com/scenery/NewSearchList.aspx?&action=getlist&page=2&kw=&pid=6&cid=80&cyid=0&sort=&isnow=0&spType=&lbtypes=&IsNJL=0&classify=0&grade=&dctrack=1%CB%871629537670551030%CB%8720%CB%873%CB%872557287248299209%CB%870&iid=0.6901326566387387

    经过增删改查操作,我们可以把该URL简化为:

    https://www.ly.com/scenery/NewSearchList.aspx?&action=getlist&page=1&pid=6&cid=80&cyid=0&isnow=0&IsNJL=0

    其中page为我们翻页的重要参数。

    打开该URL链接,如下图所示:

    Python实现旅游景点信息采集、评论分析和可视化

    通过上面的URL链接,我们可以获取到很多景点的基础信息,随机打开一个景点的详情网页并打开开发者模式,经过查找,评论数据存放在如下图的URL链接中,

    Python实现旅游景点信息采集、评论分析和可视化

    其URL链接如下所示:

    https://www.ly.com/scenery/AjaxHelper/DianPingAjax.aspx?action=GetDianPingList&sid=12851&page=1&pageSize=10&labId=1&sort=0&iid=0.48901069375088

    其中:action、labId、iid、sort为常量,sid是景点的id,page控制翻页,pageSize是每页获取的数据量。

    在上上步中,我们知道景点id的存放位置,那么构造评论数据的URL就很简单了。

    实战演练

    这次我们爬虫步骤是:

    1. 获取景点基本信息
    2. 获取评论数据
    3. 创建MySQL数据库
    4. 保存数据
    5. 创建线程池
    6. 数据分析

    获取景点基本信息

    首先我们先获取景点的名字、id、价格、特色、地点和等级,主要代码如下所示:

    def get_parse(url):response=requests.get(url,headers=headers)Xpath=parsel.Selector(response.text)data=Xpath.xpath('/html/body/div')for i in data:Scenery_data={'title':i.xpath('./div/div[1]/div[1]/dl/dt/a/text()').extract_first(),'sid':i.xpath('//div[@]/div/@sid').extract_first(),'Grade':i.xpath('./div/div[1]/div[1]/dl/dd[1]/span/text()').extract_first(), 'Detailed_address':i.xpath('./div/div[1]/div[1]/dl/dd[2]/p/text()').extract_first().replace('地址:',''),'characteristic':i.xpath('./div/div[1]/div[1]/dl/dd[3]/p/text()').extract_first(),'price':i.xpath('./div/div[1]/div[2]/div[1]/span/b/text()').extract_first(),'place':i.xpath('./div/div[1]/div[1]/dl/dd[2]/p/text()').extract_first().replace('地址:','')[6:8]}

    首先自定义方法get_parse()来发送网络请求后使用parsel.Selector()方法来解析响应的文本数据,然后通过xpath来获取数据。

    获取评论数据

    获取景点基本信息后,接下来通过景点基本信息中的sid来构造评论信息的URL链接,主要代码如下所示:

    def get_data(Scenery_data):for i in range(1,3):link = f'https://www.ly.com/scenery/AjaxHelper/DianPingAjax.aspx?action=GetDianPingList&sid={Scenery_data["sid"]}&page={i}&pageSize=100&labId=1&sort=0&iid=0.20105777381446832'response=requests.get(link,headers=headers)Json=response.json()commtent_detailed=Json.get('dpList')# 有评论数据if commtent_detailed!=None:for i in commtent_detailed:Comment_information={'dptitle':Scenery_data['title'],'dpContent':i.get('dpContent'),'dpDate':i.get('dpDate')[5:7],'lineAccess':i.get('lineAccess')}#没有评论数据elif commtent_detailed==None:Comment_information={'dptitle':Scenery_data['title'],'dpContent':'没有评论','dpDate':'没有评论','lineAccess':'没有评论'}

    首先自定义方法get_data()并传入刚才获取的景点基础信息数据,然后通过景点基础信息的sid来构造评论数据的URL链接,当在构造评论数据的URL时,需要设置pageSize和page这两个变量来获取多条评论和进行翻页,构造URL链接后就发送网络请求。

    这里需要注意的是:有些景点是没有评论,所以我们需要通过if语句来进行设置。

    创建MySQL数据库

    这次我们把数据存放在MySQL数据库中,由于数据比较多,所以我们把数据分为两种数据表,一种是景点基础信息表,一种是景点评论数据表,主要代码如下所示:

    #创建数据库def create_db():db=pymysql.connect(host=host,user=user,passwd=passwd,port=port)cursor=db.cursor()sql='create database if not exists commtent default character set utf8'cursor.execute(sql)db.close()create_table()#创建景点信息数据表def create_table():db=pymysql.connect(host=host,user=user,passwd=passwd,port=port,db='commtent')cursor=db.cursor()sql = 'create table if not exists Scenic_spot_data (title varchar(255) not null, link varchar(255) not null,Grade varchar(255) not null, Detailed_address varchar(255) not null, characteristic varchar(255)not null, price int not null, place varchar(255) not null)'cursor.execute(sql)db.close()

    首先我们调用pymysql.connect()方法来连接数据库,通过.cursor()获取游标,再通过.execute()方法执行单条的sql语句,执行成功后返回受影响的行数,然后关闭数据库连接,最后调用自定义方法create_table()来创建景点信息数据表。

    这里我们只给出了创建景点信息数据表的代码,因为创建数据表只是sql这条语句稍微有点不同,其他都一样,大家可以参考这代码来创建各个景点评论数据表。

    保存数据

    创建好数据库和数据表后,接下来就要保存数据了,主要代码如下所示:

    首先我们调用pymysql.connect()方法来连接数据库,通过.cursor()获取游标,再通过.execute()方法执行单条的sql语句,执行成功后返回受影响的行数,使用了try-except语句,当保存的数据不成功,就调用rollback()方法,撤消当前事务中所做的所有更改,并释放此连接对象当前使用的任何数据库锁。

    #保存景点数据到景点数据表中def saving_scenery_data(srr):db = pymysql.connect(host=host, user=user, password=passwd, port=port, db='commtent')cursor = db.cursor()sql = 'insert into Scenic_spot_data(title, link, Grade, Detailed_address, characteristic,price,place) values(%s,%s,%s,%s,%s,%s,%s)'try:cursor.execute(sql, srr)db.commit()except:db.rollback()db.close()

    注意:srr是传入的景点信息数据。

    创建线程池

    好了,单线程爬虫已经写好了,接下来将创建一个函数来创建我们的线程池,使单线程爬虫变为多线程,主要代码如下所示:

    urls = [f'https://www.ly.com/scenery/NewSearchList.aspx?&action=getlist&page={i}&pid=6&cid=80&cyid=0&isnow=0&IsNJL=0'for i in range(1, 6)]def multi_thread():with concurrent.futures.ThreadPoolExecutor(max_workers=8)as pool:h=pool.map(get_parse,urls)if __name__ == '__main__':create_db()multi_thread()

    创建线程池的代码很简单就一个with语句和调用map()方法

    运行结果如下图所示:

    Python实现旅游景点信息采集、评论分析和可视化

    Python实现旅游景点信息采集、评论分析和可视化

    好了,数据已经获取到了,接下来将进行数据分析。

    数据可视化

    首先我们来分析一下各个景点那个月份游玩的人数最多,这样我们就不用担心去游玩的时机不对了。

    Python实现旅游景点信息采集、评论分析和可视化

    我们发现10月、2月、1月去广州长隆飞鸟乐园游玩的人数占总体比例最多。分析完月份后,我们来看看评论情况如何:

    Python实现旅游景点信息采集、评论分析和可视化

    可以发现去好评占了绝大部分,可以说:去长隆飞鸟乐园玩耍,去了都说好。看了评论情况,评论内容有什么:

    Python实现旅游景点信息采集、评论分析和可视化

    好了,获取旅游景点信息及评论并做词云、数据可视化就讲到这里了。

    本文内容来源于网友投稿,如有侵权请联系删除。
    作者最新文章
    编程开发 Python
    相关文章 更多
    Claude Code AI编程工具实力揭秘与编程助手实测
    Claude Code AI编程工具实力揭秘与编程助手实测

    通过实测展示Claude Code在终端中如何理解自然语言指令、自动修改代码文件并处理复杂编程任务,帮助开发者评估其实际辅助能力。

    winforms教程自学入门与基础开发步骤详解
    winforms教程自学入门与基础开发步骤详解

    本教程详细讲解如何使用Visual Studio创建WinForms项目,通过添加按钮和标签控件并编写点击事件代码,实现一个基础的计数器功能,适合C#初学者快速上手Windows窗体应用开发。

    Cursor自动补全设置教程教你快速开启代码补全功能
    Cursor自动补全设置教程教你快速开启代码补全功能

    详解Cursor编辑器中自动补全功能的开启与优化设置,涵盖Tab触发机制、上下文窗口调整及模型切换,帮助开发者解决补全延迟、干扰大等问题,提升编码流畅度。

    pandas的数据格式怎么转换和设置方法教程
    pandas的数据格式怎么转换和设置方法教程

    详解Pandas中数据格式转换的核心方法,包括astype强制转换、to_numeric容错处理及日期解析技巧,解决常见类型错误并提升数据处理效率。

    VS Code中文设置方法 简体语言包安装与切换教程
    VS Code中文设置方法 简体语言包安装与切换教程

    详细介绍在Visual Studio Code中安装Chinese (Simplified)语言包的方法,包括通过扩展市场搜索、安装及自动重启切换至简体中文界面的完整步骤,帮助开发者快速将编辑器本地化。

    cursor安装过程无法更改安装位置的解决方法
    cursor安装过程无法更改安装位置的解决方法

    针对Cursor安装包默认锁定C盘且无路径选择界面的问题,提供通过手动移动文件并创建目录联结(Symbolic Link)的解决方案,实现将软件安装在其他磁盘分区。

    rust下载安装教程详解及Windows环境配置方法
    rust下载安装教程详解及Windows环境配置方法

    详解Windows系统下Rust语言的安装步骤,重点解析rustup工具链管理机制,解决环境变量配置错误及MSVC链接器缺失问题,提供可复制的命令验证方法与常见报错的因果排查思路。

    vs code怎么配置 chat实用设置教程步骤
    vs code怎么配置 chat实用设置教程步骤

    详解VS Code中Chat插件的安装与核心配置步骤,重点解决API连接失败、响应慢等常见问题,通过优化上下文设置提升代码生成质量,适合希望集成AI辅助工具的开发者阅读。

    uniapp实例教程代码详解与项目实战指南
    uniapp实例教程代码详解与项目实战指南

    本教程通过实战案例详解UniApp开发流程,包括项目初始化、页面结构解析、数据绑定与事件处理,帮助初学者快速上手跨平台应用开发。

    android studio安装教程2026
    android studio安装教程2026

    详细讲解2026年最新版Android Studio的下载与安装步骤,涵盖JDK环境检查、组件选择及初始配置,助您顺利开启安卓应用开发之旅。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    macOS软件
    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    Mac软件 更多
    Blender
    Blender
    Windows、macOS 和 Linux

    Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。

    灵活计算器
    灵活计算器
    macOS/iOS/Android

    灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

    赤友清理大师
    赤友清理大师
    macOS

    赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

    WINDOWS 更多
    Blender
    Blender
    Windows、macOS 和 Linux

    Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。

    Windows 10
    Windows 10
    Windows

    Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

    极度公式
    极度公式
    Windows/macOS/Linux

    极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。