【旅游景点项目日记 | 第二篇】基于Python中的Selenium爬取携程旅游网景点详细数据

这篇具有很好参考价值的文章主要介绍了【旅游景点项目日记 | 第二篇】基于Python中的Selenium爬取携程旅游网景点详细数据。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

携程旅游景点数据爬取,selenium,项目,python

Gitee仓库地址:travel-server:景点旅游项目服务端

3.基于Python中的Selenium爬取携程旅游网景点详细数据

3.1前提环境

  1. 确保安装python3.x环境
  2. 以管理员身份打开cmd,安装selenium、pymysql、datetime,默认安装最新版即可
pip install selenium
pip install pymysql
pip install datetime
  1. 确保chrome安装对应版本的驱动(将该驱动放在chrome安装路径下),用于控制chrome浏览器,并将路径添加到环境变量的Path变量中,如图所示!

    #安装chrome驱动教程链接:
    https://blog.csdn.net/linglong_L/article/details/136283810
    

    携程旅游景点数据爬取,selenium,项目,python

3.2思路

  1. 搜索指定城市景点,网站通过分页进行展示
  2. 使用selenium每个景点的详细访问路径,并点击该路径获取详细景点信息,再通过正则表达式获取需要的内容

携程旅游景点数据爬取,selenium,项目,python

  1. 如下图,景点的详细信息有:景点名称、景点等级(1-5A)、景点地址、开放时间(有两种,我们采用下面的)、联系电话、景点介绍、景点图片等内容

    携程旅游景点数据爬取,selenium,项目,python

3.3代码详讲

3.3.1查询指定城市的所有景点

  • 控制打开chrome,并访问指定查询所有景点路径
    def __init__(self):
        options = Options()
        options.add_argument('--headless')
        service = Service()
        self.chrome = Chrome(service=service)
        self.chrome.get(
            'https://huodong.ctrip.com/things-to-do/list?pagetype=city&citytype=dt&keyword=%E6%A2%85%E5%B7%9E&id=523&name=%E6%A2%85%E5%B7%9E&pshowcode=Ticket2&kwdfrom=srch&bookingtransactionid=1711160613361_6064')
        time.sleep(3)
        self.page = 1
        self.headers = {
            'cookie': 'suid=lh/P1+4RKuhAYg684ErS+g==; suid=lh/P1+4RKuhAYg684ErS+g==',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36',
        }

3.3.2获取详细景点的访问路径

  • 使用selenium的根据class定位元素方法,找到详细景点的href属性,即为该景点的访问路径
  • 并通过page属性控制访问的页数
	#获取景点请求路径
    def get_url(self):
        while True:

            content = self.chrome.find_element(By.CLASS_NAME, "right-content-list").get_attribute('innerHTML')
            cons = re.findall(r'href="(.*?)" title="(.*?)"', content)
            for con in cons:
                self.detail_url = 'https:' + con[0]
                self.title = con[1]
                print(self.detail_url, self.title)
                self.get_detail()
            self.chrome.find_element(By.CLASS_NAME,'u_icon_enArrowforward').click()
            time.sleep(1)

            self.page += 1
            if self.page == 120:
                break

携程旅游景点数据爬取,selenium,项目,python

3.3.3获取景点的详细信息

  • 景点的详细信息有:景点名称、景点等级(1-5A)、景点地址、开放时间(有两种,我们采用下面的)、联系电话、景点介绍、景点图片等内容
  • 通过正则表达式获取,详细代码如下:
  • 并每次获取详细信息之后,将信息保存到mysql数据库中
    def get_detail(self):
        detail_con = requests.get(self.detail_url, verify=False, headers=self.headers).text
        # time.sleep(2)
        '''使用正则获取信息'''
        self.title = ''.join(re.findall(r'<div class="title"><h1>(.*?)<', detail_con, re.DOTALL))
        print('景点名称:'+self.title)

        #self.rank = ''.join(re.findall(r'rankText">(.*?)<', detail_con, re.DOTALL))

        self.address = ''.join(re.findall(r'地址</p><p class="baseInfoText">(.*?)<', detail_con, re.DOTALL))
        self.mobile = ''.join(re.findall(r'官方电话</p><p class="baseInfoText">(.*?)<', detail_con, re.DOTALL))
        self.quality_grade= ''.join(re.findall(r'<div class="titleTips"><span>(.*?)<!--', detail_con, re.DOTALL))
        #self.openTime = ''.join(re.findall(r'开放时间</div><div class="moduleContent">(.*?)<', detail_con, re.DOTALL))

        first_three_characters = self.address[:3]
        print('所在省份城市:'+'广东省'+first_three_characters)

        print('详细地址:'+self.address)
        #print('开放时间:'+self.openTime)
        print('电话:'+self.mobile)
        print('等级:'+self.quality_grade)
        if self.quality_grade=='':
            self.quality_grade=0

        '''使用xpath获取信息'''
        ret = etree.HTML(detail_con)
        desc_cons = ret.xpath('//div[@class="detailModule normalModule"]//div[@class="moduleContent"]')
        desc_titles = ret.xpath('//div[@class="detailModule normalModule"]//div[@class="moduleTitle"]')
        desc_list = []
        desc_title_list = []
        for d in desc_cons:
            des = ''.join(d.xpath('.//text()'))
            desc_list.append(des)
        for d in desc_titles:
            des = ''.join(d.xpath('.//text()'))
            desc_title_list.append(des)
        desc_dict = dict(zip(desc_title_list, desc_list))
        #print(desc_dict)

        first_value = list(desc_dict.values())[:2]  # 获取前两个值
        if len(first_value) >= 1:
            introduction = first_value[0]
        else:
            introduction = ''

        if len(first_value) >= 2:
            opening_hours = first_value[1]
        else:
            opening_hours = ''

        print('介绍:'+introduction)
        print('开放时间:'+ opening_hours)

        '''获取图片链接'''
        img_list = []
        imgs = re.findall(r'background-image:url\((.*?)\)', detail_con, re.DOTALL)
        for img in imgs:
            '''匹配到的同一张图片会有两种尺寸,我们只要大图,所以把尺寸为521*391的匹配出来即可'''
            image = re.search(r'521_391', img)
            if image:
                img_list.append(img)
        print(",".join(img_list))

        conn = pymysql.connect(host='localhost', user='root', password='root',
                               database='travel_ams', charset='utf8mb4')
        cursor = conn.cursor()

        sql = "INSERT INTO ams_attraction (attraction_name, quality_grade, province_city, location, open_hour, phone, introduction, images, add_time) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)"
        values = (self.title, self.quality_grade, '广东省'+first_three_characters, self.address, opening_hours, self.mobile, introduction,",".join(img_list)  ,datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
        cursor.execute(sql, values)

        conn.commit()
        conn.close()

        #self.get_ticket()

3.4数据库设计

travel_ams数据库的ams_attraction表

字段名 字段类型 是否为主键 是否有唯一约束 是否有非空约束 注释
attraction_id int 景点id,自增
attraction_name varchar(20) 景点名称
resource_type_id int 景点资源类型id
quality_grade int 景点等级
province_city varchar(20) 景点所在省份城市
location varchar(1000) 详细位置
open_hour varchar(1000) 开放时间
phone varchar(1000) 电话
introduction varchar(10000) 景点介绍
images varchar(1000) 景点图片列表
staus int 状态【1为显示,0为不显示】
add_time datetime 添加时间
update_time datetime 修改时间

创建表语句如下:

CREATE TABLE ams_attraction (
    attraction_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '景点id,自增',
    attraction_name VARCHAR(20) COMMENT '景点名称',
    resource_type_id INT COMMENT '景点资源类型id',
    province_city VARCHAR(20) COMMENT '景点所在省份城市',
    location VARCHAR(1000) COMMENT '详细位置',
    open_hour VARCHAR(1000) COMMENT '开放时间',
    phone VARCHAR(1000) COMMENT '电话',
    introduction VARCHAR(10000) COMMENT '景点介绍',
    images VARCHAR(1000) COMMENT '景点图片列表',
    status INT COMMENT '状态【1为显示,0为不显示】',
    add_time DATETIME COMMENT '添加时间',
    update_time DATETIME COMMENT '修改时间'
);

3.5全部代码

  • 执行该main方法,即可完成导入指定访问路径的景点数据
  • 可以在控制台查询是否导入成功
import pandas
import re
import time
import requests
import urllib3
from lxml import etree
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import pymysql
import datetime



urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class Jy_jd(object):
    def __init__(self):
        options = Options()
        options.add_argument('--headless')
        service = Service()
        self.chrome = Chrome(service=service)
        self.chrome.get(
            'https://huodong.ctrip.com/things-to-do/list?pagetype=city&citytype=dt&keyword=%E6%A2%85%E5%B7%9E&id=523&name=%E6%A2%85%E5%B7%9E&pshowcode=Ticket2&kwdfrom=srch&bookingtransactionid=1711160613361_6064')
        time.sleep(3)
        self.page = 1
        self.headers = {
            'cookie': 'suid=lh/P1+4RKuhAYg684ErS+g==; suid=lh/P1+4RKuhAYg684ErS+g==',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36',
        }

    #获取景点请求路径
    def get_url(self):
        while True:

            content = self.chrome.find_element(By.CLASS_NAME, "right-content-list").get_attribute('innerHTML')
            cons = re.findall(r'href="(.*?)" title="(.*?)"', content)
            for con in cons:
                self.detail_url = 'https:' + con[0]
                self.title = con[1]
                print(self.detail_url, self.title)
                self.get_detail()
            self.chrome.find_element(By.CLASS_NAME,'u_icon_enArrowforward').click()
            time.sleep(1)

            self.page += 1
            if self.page == 120:
                break

    def get_detail(self):
        detail_con = requests.get(self.detail_url, verify=False, headers=self.headers).text
        # time.sleep(2)
        '''使用正则获取信息'''
        self.title = ''.join(re.findall(r'<div class="title"><h1>(.*?)<', detail_con, re.DOTALL))
        print('景点名称:'+self.title)

        #self.rank = ''.join(re.findall(r'rankText">(.*?)<', detail_con, re.DOTALL))

        self.address = ''.join(re.findall(r'地址</p><p class="baseInfoText">(.*?)<', detail_con, re.DOTALL))
        self.mobile = ''.join(re.findall(r'官方电话</p><p class="baseInfoText">(.*?)<', detail_con, re.DOTALL))
        self.quality_grade= ''.join(re.findall(r'<div class="titleTips"><span>(.*?)<!--', detail_con, re.DOTALL))
        #self.openTime = ''.join(re.findall(r'开放时间</div><div class="moduleContent">(.*?)<', detail_con, re.DOTALL))

        first_three_characters = self.address[:3]
        print('所在省份城市:'+'广东省'+first_three_characters)

        print('详细地址:'+self.address)
        #print('开放时间:'+self.openTime)
        print('电话:'+self.mobile)
        print('等级:'+self.quality_grade)
        if self.quality_grade=='':
            self.quality_grade=0

        '''使用xpath获取信息'''
        ret = etree.HTML(detail_con)
        desc_cons = ret.xpath('//div[@class="detailModule normalModule"]//div[@class="moduleContent"]')
        desc_titles = ret.xpath('//div[@class="detailModule normalModule"]//div[@class="moduleTitle"]')
        desc_list = []
        desc_title_list = []
        for d in desc_cons:
            des = ''.join(d.xpath('.//text()'))
            desc_list.append(des)
        for d in desc_titles:
            des = ''.join(d.xpath('.//text()'))
            desc_title_list.append(des)
        desc_dict = dict(zip(desc_title_list, desc_list))
        #print(desc_dict)

        first_value = list(desc_dict.values())[:2]  # 获取前两个值
        if len(first_value) >= 1:
            introduction = first_value[0]
        else:
            introduction = ''

        if len(first_value) >= 2:
            opening_hours = first_value[1]
        else:
            opening_hours = ''

        print('介绍:'+introduction)
        print('开放时间:'+ opening_hours)

        '''获取图片链接'''
        img_list = []
        imgs = re.findall(r'background-image:url\((.*?)\)', detail_con, re.DOTALL)
        for img in imgs:
            '''匹配到的同一张图片会有两种尺寸,我们只要大图,所以把尺寸为521*391的匹配出来即可'''
            image = re.search(r'521_391', img)
            if image:
                img_list.append(img)
        print(",".join(img_list))

        conn = pymysql.connect(host='localhost', user='root', password='root',
                               database='travel_ams', charset='utf8mb4')
        cursor = conn.cursor()

        sql = "INSERT INTO ams_attraction (attraction_name, quality_grade, province_city, location, open_hour, phone, introduction, images, add_time) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)"
        values = (self.title, self.quality_grade, '广东省'+first_three_characters, self.address, opening_hours, self.mobile, introduction,",".join(img_list)  ,datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
        cursor.execute(sql, values)

        conn.commit()
        conn.close()

        #self.get_ticket()

    #获取门票
    def get_ticket(self):
        id = self.detail_url.split('/')[-1]
        print(id)
        ticket_url = f'https://piao.ctrip.com/ticket/dest/{id}?onlyContent=true&onlyShelf=true'
        ticket_res = requests.get(ticket_url, verify=False, headers=self.headers).text
        # time.sleep(1)
        ticket_ret = etree.HTML(ticket_res)
        ticket = ticket_ret.xpath('//table[@class="ticket-table"]//div[@class="ttd-fs-18"]/text()')
        price = ticket_ret.xpath(
            '//table[@class="ticket-table"]//td[@class="td-price"]//strong[@class="ttd-fs-24"]/text()')
        print(ticket)
        print(price)
        '''拿到的列表里可能存在不确定数量的空值,所以这里用while True把空值全部删除,这样才可以确保门票种类与价格正确对应上'''
        while True:
            try:
                ticket.remove(' ')
            except:
                break
        while True:
            try:
                price.remove(' ')
            except:
                break
        '''
            这里多一个if判断是因为我发现有些详情页即便拿到门票信息并剔除掉空值之后仍然存在无法对应的问题,原因是网页规则有变动,
            所以一旦出现这种情况需要使用新的匹配规则,否则会数据会出错(不会报错,但信息对应会错误)
        '''
        if len(ticket) != len(price):
            ticket = ticket_ret.xpath(
                '//table[@class="ticket-table"]/tbody[@class="tkt-bg-gray"]//a[@class="ticket-title "]/text()')
            price = ticket_ret.xpath('//table[@class="ticket-table"]//strong[@class="ttd-fs-24"]/text()')
            while True:
                try:
                    ticket.remove(' ')
                except:
                    break
            while True:
                try:
                    price.remove(' ')
                except:
                    break
            print(ticket)
            print(price)
        ticket_dict = dict(zip(ticket, price))
        print(ticket_dict)

if __name__ == '__main__':

    jy_jd = Jy_jd()
    jy_jd.get_url()


3.6效果图

携程旅游景点数据爬取,selenium,项目,python
携程旅游景点数据爬取,selenium,项目,python文章来源地址https://www.toymoban.com/news/detail-849455.html

到了这里,关于【旅游景点项目日记 | 第二篇】基于Python中的Selenium爬取携程旅游网景点详细数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于Python热门旅游景点数据分析系统设计与实现

    博主介绍 : ✌全网粉丝30W+,csdn特邀作者、博客专家、CSDN新星计划导师、java优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ 🍅 文末获取源码联系 🍅 👇🏻 精彩专栏 推荐订阅 👇🏻 不然下次找不到哟 java项目精品实战

    2024年02月11日
    浏览(39)
  • 基于PYTHON django四川旅游景点推荐系统

    摘 要 基于四川旅游景点推荐系统的设计与实现是一个专为四川旅游景点为用户打造的旅游网站。该课题基于网站比较流行的Python 语言系统架构,B/S三层结构模式,通过Maven项目管理工具进行Jar包版本的控制。本系统用户可以发布个人游记,查看景点使用户达到良好的旅游体验

    2024年02月02日
    浏览(52)
  • 【爬虫实战项目】Python爬虫批量旅游景点信息数据并保存本地(附源码)

    今天给大家介绍的是Python爬虫批量下载旅游景点信息数据,在这里给需要的小伙伴们代码,并且给出一点小心得。 首先是爬取之前应该尽可能伪装成浏览器而不被识别出来是爬虫,基本的是加请求头,但是这样的纯文本数据爬取的人会很多,所以我们需要考虑更换代理IP和随

    2023年04月20日
    浏览(38)
  • 基于spark的热门旅游景点门票数据可视化分析系统

    热门旅游景点数据分析系统综合网络空间开发设计要求。目的是将传统管理方式转换为在网上管理,完成热门旅游景点数据分析管理的方便快捷、安全性高、交易规范做了保障,目标明确。热门旅游景点数据分析系统功能主要包括个人中心、门票信息管理、名宿信息管理、系

    2024年04月14日
    浏览(46)
  • 基于hive的安顺旅游景点数据分析的设计与实现

    博主介绍 : ✌ 全网粉丝30W+,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流 ✌ 主要内容: SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、P

    2024年03月12日
    浏览(40)
  • 基于Java(SpringBoot框架)毕业设计作品成品(44)旅游景点旅游线路旅游网站管理系统设计与实现

    博主介绍: 《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、PPT、论文模版

    2024年02月06日
    浏览(42)
  • 基于微信小程序的旅游景点预约评价系统设计与实现

    💗博主介绍:✌全网粉丝10W+,CSDN全栈领域优质创作者,博客之星、掘金/华为云/阿里云等平台优质作者。 👇🏻 精彩专栏 推荐订阅👇🏻 计算机毕业设计精品项目案例-200套 🌟 文末获取源码+数据库+文档 🌟 感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编

    2024年02月02日
    浏览(41)
  • 基于Python+Spark的热门旅游景点数据可视化分析系统的设计与实现

    🔥作者:雨晨源码🔥 💖简介:java、微信小程序、安卓;定制开发,远程调试 代码讲解,文档指导,ppt制作💖 精彩专栏推荐订阅:在下方专栏👇🏻👇🏻👇🏻👇🏻 Java精彩实战毕设项目案例 小程序精彩项目案例 Python实战项目案例 ​💕💕 文末获取源码 本次文章主要是

    2024年02月04日
    浏览(47)
  • 基于Java旅游景区景点订票系统的设计与实现(Springboot框架) 参考文献

     博主介绍 :黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、

    2024年02月20日
    浏览(35)
  • 基于微信小程序旅游景点景区售票系统设计与实现 毕业设计论文大纲提纲参考

     博主介绍 :黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩。 项目配有对应开发文档、

    2024年02月19日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包