python简直旅游好帮手:【爬虫+数据分析】这不玩个遍?

嗨害大家好鸭~我是小熊猫❤

就快放假啦~

大概还有十几个小时的样子吧

不知道大家的假期有什么样的安排呢?

不过大家一定要保住自己的健康码啊!!!

请添加图片描述

趁现在,先来用python做一个旅游攻略

知识点:

requests  发送网络请求
parsel    解析数据
csv       保存数据

第三方库:

requests >>> pip install requests
parsel >>> pip install parsel

模块安装:

  • 按住键盘 win + r, 输入cmd回车
  • 打开命令行窗口, 在里面输入 pip install 模块名
  • 开发环境:

    版 本: python 3.8
    

    +python安装包 安装教程视频
    +pycharm 社区版 专业版 及 激活码文末名片获取

    请添加图片描述

    python学习方向:

    爬虫开发: 批量采集网络当中数据内容(图片 文本 视频 音频)
    数据分析: 对大量数据 进行处理分析, 做可视化, 预测
    网站开发: 搭建网站服务 例如 淘宝 京东 豆瓣 知乎...
    人工智能
    

    案例思路分析:

    1. 明确今天的目的, 我们需要什么数据
        出发日期 天数 人均费用 人物 玩法 地点 浏览量...
    2. 分析网页 确定我们的数据来源
        静态页面
    

    请添加图片描述

    代码实现步骤:

    1. 向目标网站发送网络请求
        https://travel.qunar.com/travelbook/list.htm?order=hot_heat
    2. 获取数据 网页源代码
    3. 筛选我们需要的数据 所有的详情页链接
    4. 向 每一个详情页 链接发送网络请求
    5. 获取数据 网页源代码
    6. 提取数据
        出发日期 天数 人均费用 人物 玩法 地点 浏览量...
    7. 保存数据
    8. 多页爬取
    9. 做一个可视化分析 旅游景点推荐
    

    导入模块

    import random
    import time
    import requests     # 发送网络请求
    import parsel       # 筛选数据模块
    import csv          # 保存数据
    

    请添加图片描述

    爬取旅游网数据

    1. 向目标网站发送网络请求
    csv_qne = open('去哪儿.csv', mode='a', encoding='utf-8', newline='')
    csv_writer = csv.writer(csv_qne)
    csv_writer.writerow(['地点', '短评', '出发时间', '天数','人均费用','人物','玩法','浏览量','详情页'])
    for page in range(1, 201):
        url = f'https://travel.qunar.com/travelbook/list.htm?page={page}&order=hot_heat'
        # 写爬虫 没有太大区别
        # post里面需要加一些请求参数
        # 在网站开发当中 get请求不是很安全的请求 有长度限制的
        # post 更加安全 提交表单数据内容 没有长度限制的
        response = requests.get(url)
        # <Response [200]>: 访问成功了, 接下来我们就只需要拿数据就行了
    
    2. 获取数据 网页源代码
        html_data = response.text
    
    3. 筛选我们需要的数据 所有的详情页链接
        selector = parsel.Selector(html_data)
        # css选择器提取网页内容
        # 需要有网页开发基础
        url_list = selector.css('body > div.qn_mainbox > div > div.left_bar > ul > li > h2 > a::attr(href)').getall()
        for detail_url in url_list:
            detail_id = detail_url.replace('/youji/', '')
            detail_url = 'https://travel.qunar.com/travelbook/note/' + detail_id
    
    4. 向 每一个详情页 链接发送网络请求
            response_1 = requests.get(detail_url)
    
    5. 获取数据 网页源代码
            data_html_1 = response_1.text
    
    6. 提取数据
            #   出发日期 天数 人均费用 人物 玩法 地点 浏览量...
            selector_1 = parsel.Selector(data_html_1)
            # ::text 提取标签里面文本内容 *所有
            # 标题
            title = selector_1.css('.b_crumb_cont *:nth-child(3)::text').get()
            # 短评
            comment = selector_1.css('.title.white::text').get()
            # 浏览量
            count = selector_1.css('.view_count::text').get()
            # 出发日期
            date = selector_1.css('#js_mainleft > div.b_foreword > ul > li.f_item.when > p > span.data::text').get()
            # 天数
            days = selector_1.css('#js_mainleft > div.b_foreword > ul > li.f_item.howlong > p > span.data::text').get()
            # 人均费用
            money = selector_1.css('#js_mainleft > div.b_foreword > ul > li.f_item.howmuch > p > span.data::text').get()
            # 人物
            character = selector_1.css('#js_mainleft > div.b_foreword > ul > li.f_item.who > p > span.data::text').get()
            # 玩法
            play_list = selector_1.css('#js_mainleft > div.b_foreword > ul > li.f_item.how > p > span.data span::text').getall()
            play = ' '.join(play_list)
            print(title, comment, date, days, money, character, play, count, detail_url)
            csv_writer.writerow([title, comment, date, days, money, character, play, count, detail_url])
            time.sleep(random.randint(3, 5))
    csv_qne.close()
    

    请添加图片描述

    数据分析代码

    #%%
    
    import pandas as pd
    from pyecharts.commons.utils import JsCode
    from pyecharts.charts import *
    from pyecharts import options as opts
    
    #%%
    
    data = pd.read_csv('去哪儿_数分.csv')
    data
    
    #%%
    
    data.info()
    
    #%%
    
    data = data[~data['地点'].isin(['攻略'])]
    data = data[~data['天数'].isin(['99+'])]
    data
    
    #%%
    
    data.drop_duplicates(inplace=True)
    
    #%%
    
    data['人均费用'].fillna(0, inplace=True)
    data['人物'].fillna('独自一人', inplace=True)
    data['玩法'].fillna('没有', inplace=True)
    
    #%%
    
    data['天数'] = data['天数'].astype(int)
    
    #%%
    
    data = data[data['人均费用'].values>200]
    data = data[data['天数']<=15]
    data
    
    #%%
    
    data = data.reset_index(drop=True)
    data
    
    #%%
    
    data = data.reset_index(drop=True)
    data
    
    #%%
    
    def Month(e):
        m = str(e).split('/')[2]
        if m=='01':
            return '一月'
        if m=='02':
            return '二月'
        if m=='03':
            return '三月'
        if m=='04':
            return '四月'
        if m=='05':
            return '五月'
        if m=='06':
            return '六月'
        if m=='07':
            return '七月'
        if m=='08':
            return '八月'
        if m=='09':
            return '九月'
        if m=='10':
            return '十月'
        if m=='11':
            return '十一月'
        if m=='12':
            return '十二月'
    
    #%%
    
    data['旅行月份'] = data['出发时间'].apply(Month)
    data['出发时间']=pd.to_datetime(data['出发时间'])
    data
    
    #%%
    
    import re
    
    #%%
    
    def Look(e):
        if '万' in e:
            num1 = re.findall('(.*?)万',e)
            return float(num1[0])*10000
        else:
            return float(e)
    
    #%%
    
    data['浏览次数'] = data['浏览量'].apply(Look)
    data.drop(['浏览量'],axis = 1,inplace = True)
    data['浏览次数'] = data['浏览次数'].astype(int)
    data.head()
    
    #%%
    
    data1 = data
    data1['地点'].value_counts().head(10)
    
    #%%
    
    loc = data1['地点'].value_counts().head(10).index.tolist()
    print(loc)
    loc_data = data1[data1['地点'].isin(loc)]
    price_mean = round(loc_data['人均费用'].groupby(loc_data['地点']).mean(),1)
    print(price_mean)
    price_mean2 = [1630.1,1862.9,1697.9,1743.4,1482.4,1586.4,1897.0,1267.5,1973.8,1723.7]
    
    #%% md
    
    ## 一、旅游胜地Top10及对应费用
    
    #%%
    
    m2 = data1['地点'].value_counts().head(10).index.tolist()
    n2 = data1['地点'].value_counts().head(10).values.tolist()
    
    #%%
    
    bar=(
        Bar(init_opts=opts.InitOpts(height='500px',width='1000px',theme='dark'))
        .add_xaxis(m2)
        .add_yaxis(
            '目的地Top10',
            n2,
            label_opts=opts.LabelOpts(is_show=True,position='top'),
            itemstyle_opts=opts.ItemStyleOpts(
                color=JsCode("""new echarts.graphic.LinearGradient(
                0, 0, 0, 1,[{offset: 0,color: 'rgb(255,99,71)'}, {offset: 1,color: 'rgb(32,178,170)'}])
                """
                )
            )
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(
                title='目的地Top10'),
                xaxis_opts=opts.AxisOpts(name='景点名称',
                type_='category',                                           
                axislabel_opts=opts.LabelOpts(rotate=90),
            ),
            yaxis_opts=opts.AxisOpts(
                name='数量',
                min_=0,
                max_=120.0,
                splitline_opts=opts.SplitLineOpts(is_show=True,linestyle_opts=opts.LineStyleOpts(type_='dash'))
            ),
            tooltip_opts=opts.TooltipOpts(trigger='axis',axis_pointer_type='cross')
        )
    
        .set_series_opts(
            markline_opts=opts.MarkLineOpts(
                data=[
                    opts.MarkLineItem(type_='average',name='均值'),
                    opts.MarkLineItem(type_='max',name='最大值'),
                    opts.MarkLineItem(type_='min',name='最小值'),
                ]
            )
        )
    )
    bar.render_notebook()
    
    #%%
    
    bar=(
        Bar(init_opts=opts.InitOpts(height='500px',width='1000px',theme='dark'))
        .add_xaxis(loc)
        .add_yaxis(
            '人均费用',
            price_mean2,
            label_opts=opts.LabelOpts(is_show=True,position='top'),
            itemstyle_opts=opts.ItemStyleOpts(
                color=JsCode("""new echarts.graphic.LinearGradient(
                0, 0, 0, 1,[{offset: 0,color: 'rgb(255,99,71)'}, {offset: 1,color: 'rgb(32,178,170)'}])
                """
                )
            )
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(
                title='各景点人均费用'),
                xaxis_opts=opts.AxisOpts(name='景点名称',
                type_='category',                                           
                axislabel_opts=opts.LabelOpts(rotate=90),
            ),
            yaxis_opts=opts.AxisOpts(
                name='数量',
                min_=0,
                max_=2000.0,
                splitline_opts=opts.SplitLineOpts(is_show=True,linestyle_opts=opts.LineStyleOpts(type_='dash'))
            ),
            tooltip_opts=opts.TooltipOpts(trigger='axis',axis_pointer_type='cross')
        )
    
        .set_series_opts(
            markline_opts=opts.MarkLineOpts(
                data=[
                    opts.MarkLineItem(type_='average',name='均值'),
                    opts.MarkLineItem(type_='max',name='最大值'),
                    opts.MarkLineItem(type_='min',name='最小值'),
                ]
            )
        )
    )
    bar.render_notebook()
    
    #%%
    
    data1['天数'].value_counts()
    
    #%%
    
    data1['旅行时长'] = data1['天数'].apply(lambda x:str(x) + '天')
    data1
    
    #%%
    
    data1['人物'].value_counts()
    
    #%%
    
    m = data1['浏览次数'].sort_values(ascending=False).index[:].tolist()
    
    #%%
    
    data1 = data1.loc[m]
    data1 = data1.reset_index(drop = True)
    data1
    
    #%%
    
    data1['旅行月份'].value_counts()
    
    #%%
    
    word_list = []
    for i in data1['玩法']:
        s = re.split('\xa0',i)
        word_list.append(s)  
    dict = {}
    for j in range(len(word_list)):
        for i in word_list[j]:
            if i not in dict:
                dict[i] = 1
            else:
                dict[i]+=1
    #print(dict)
    list = []
    for item in dict.items():
        list.append(item)
    for i in range(1,len(list)):
        for j in range(0,len(list)-1):
            if list[j][1]<list[j+1][1]:
                list[j],list[j+1] = list[j+1],list[j]
    print(list)
    
    #%%
    
    data1['旅行月份'].value_counts()
    #%%
    
    m1 = data1['人物'].value_counts().index.tolist()
    n1 = data1['人物'].value_counts().values.tolist()
    #%% md
    
    ## 出游方式分析
    #%%
    
    pie = (Pie(init_opts=opts.InitOpts(theme='dark', width='1000px', height='800px'))
           .add("", [z for z in zip(m1,n1)],
                radius=["40%", "65%"])
           .set_global_opts(title_opts=opts.TitleOpts(title="去哪儿\n\n出游结伴方式", pos_left='center', pos_top='center',
                                                   title_textstyle_opts=opts.TextStyleOpts(
                                                       color='#FF6A6A', font_size=30, font_weight='bold'),
                                                   ),
                            visualmap_opts=opts.VisualMapOpts(is_show=False, 
                                              min_=38,
                                              max_=641,
                                              is_piecewise=False,
                                              dimension=0,
                                              range_color=['#9400D3', '#008afb', '#ffec4a', '#FFA500','#ce5777']),
                            legend_opts=opts.LegendOpts(is_show=False, pos_top='5%'),
                            )
           .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}", font_size=12),
                            tooltip_opts=opts.TooltipOpts(trigger="item", formatter="{b}: {c}"),
                            itemstyle_opts={"normal": {
                                                        "barBorderRadius": [30, 30, 30, 30],
                                                        'shadowBlur': 10,
                                                        'shadowColor': 'rgba(0,191,255,0.5)',
                                                        'shadowOffsetY': 1,
                                                        'opacity': 0.8
                                                    }
                                           })
            
                            )
    pie.render_notebook()
    #%%
    
    m3 = data1['出发时间'].value_counts().sort_index()[:]
    m4 = m3['2021'].index
    n4 = m3['2021'].values
    #%%
    
    m3['2021'].sort_values().tail(10)
    
    ``````c
    #%% md
    
    ## 出游时间分析
    #%%
    
    line = (
        Line()
        .add_xaxis(m4.tolist())
        .add_yaxis('',n4.tolist())
    )
    line.render_notebook()
    #%%
    
    line = (
        Line()
        .add_xaxis(m4.tolist())
        .add_yaxis('',n4.tolist())
    )
    line.render_notebook()
    

    (完整代码文末名片获取)

    综上述分析可得到一些结论:

    1. 个人认为性价比较高的旅游城市:三亚、成都。

    2. 旅游天数大多控制在2-5天内,不宜过多。

    3. 三五好友一起旅游是最令人们喜欢的出游方式。

    4. “摄影”与“美食”已成为旅游的代名词。

    请添加图片描述
    今天的文章就是这样啦~

    我是小熊猫,咱下篇文章再见啦(✿◡‿◡)

    请添加图片描述

    物联沃分享整理
    物联沃-IOTWORD物联网 » python简直旅游好帮手:【爬虫+数据分析】这不玩个遍?

    发表评论