国庆长假已结束,Python 告诉你 6 亿国人都去哪儿浪了附源码

看到了网上的一篇文章,把完整源码附上
据新华网消息,整个国庆长假外出游玩人次达 6.37 亿人次,那么这么多人都到哪儿去玩了呢,今天我们就用 Python 做一个全国热门景区热点图。

入口

先说程序入口:https://piao.qunar.com/ticket/list_热门景点.html?from=mps_search_suggest_h

发现去哪儿网有一个「热门景点」的内页,在首页输入框直接输入「热门景点」即可直达该页面。该网站还将这些热门景点进行了分类,比如人文景观,城市风貌,古建筑等。同时我们需要的景点名称,城市,景区级别以及景区地址等信息都可以从该页面获取的到。
打开去哪儿网,首页输入「热门景点」仔细观察页面最上方的 URL 你会发现惊喜。其中 subject 就是景点主题,而 page 看样子则是页码,点击下一页验证一下,page 变成 2 了,没猜错。
分析完 URL 之后,再来看看数据从什么地方获取的,切换到浏览器开发者模式,浏览下我们发现所有的景点数据都在一个叫做 ”search-list“ 的 div 中。针对单个景点,其数据是在一个 class = ‘sight_item’ 的 div 中。接下来就是解析页面原属,将景点,省市,时间,热度等数据做分析。

采集数据

数据源头已经分析完毕,接下来就可以开始我们的爬虫编码了,首先定义好我们的准备获取全国景点的主题。为了方便后续操作,我们可以将解析好的数据保存到 csv 文件中。

import requests
import csv
import time
from bs4 import BeautifulSoup
subjects = ['文化古迹', '自然风光', '农家度假', '游乐场', '展馆', '古建筑', '城市观光']

excel_file = open('data.csv', 'w', encoding='utf-8', newline='')
writer = csv.writer(excel_file)
writer.writerow(['名称', '城市', '类型', '级别', '热度', '地址'])

其次我们需要一个下载网页内容的函数,该函数接受一个 URL 参数,之后返回该 URL 对应的网页内容,同时为了更真实的模拟浏览器请求,需要添加 Headers。

headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36',
    'accept-encoding': 'gzip, deflate, br',
    'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
    'referer': 'https://piao.qunar.com/',
    'cookie': 'xxxyyyzzz...'
}

def get_page_html(url):
    try:
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        return None

获取到内容之后,我们还需要一个解析函数,该函数接收一个网页文本,然后将我们所需要的「名称, 城市, 类型, 级别, 热度, 地址」信息解析出来,并写入 csv 文件。

def parse_content(content, subject):
    if not content:
        return;
    soup = BeautifulSoup(content, "html.parser")
    search_list = soup.find(id='search-list')
    items = search_list.find_all('div', class_="sight_item")
    for item in items:
        name = item['data-sight-name']
        districts = item['data-districts']
        address = item['data-address']
        level = item.find('span', class_='level')
        level = level.text if level else ''
        star = item.find('span', class_='product_star_level')
        star = star.text if star else ''
        writer.writerow([name, districts, subject, level, star, address])

至此我们已经准备好,下载函数,解析函数,现在只需要直接遍历主题,拼接 URL 调用相关函数即可。为了防止被禁封 IP,每次请求之后让程序暂停 5 秒。

def get_data():
    for subject in subjects:
        for page in range(5):    #抓5页的数据就可以了,盗亦有道啊
            page = page + 1
            url = F'https://piao.qunar.com/ticket/list.htm?keyword=热门景点&region=&from=mps_search_suggest&subject={subject}&page={page}&sku='
            print(url)
            content = get_page_html(url)
            parse_content(content, subject, url)
            time.sleep(5)

数据分析

获取到全国的旅游数据之后,就可以开始分析了。为了让操作方便,引入 pandas,先仔细看下我们的数据格式。首先热度一列里面含有中文,需要分割,其次因为热度数值是小数不方便操作,因此我们决定将热度扩大 1000 倍,因为是整体扩大了 1000 倍,因此并不会影响分析结果。

之后我们需要解析出该景点所在的城市。同样是分割字符串。同时因为还有一些地点是地图无法识别的,所以要去除。

import csv
import pandas as pd
from pyecharts.globals import ChartType
from pyecharts.charts import Geo
from pyecharts import options as opts
data = []
with open(r'data.csv', 'r',encoding='utf8') as f:
    reader = csv.reader(f)
    header = next(reader)
    for row in reader:
        data.append(row)

df_data = []
for row in data:
    try:    #可能某些数据有错误,所以加上一个监测
        city = row[1].split('·')[1]
    except:
        continue
        
    if city in ['保亭', '德宏', '湘西', '陵水', '黔东南', '黔南']:
        continue
    star = row[4].split('热度')[1].strip()
    star = int(float(star) * 1000)
    df_data.append([row[0], city, row[3], star])

df = pd.DataFrame(df_data, columns=['name', 'city', 'level', 'star'])


data = df.groupby(by=['city'])['star'].sum()
citys = list(data.index)
city_stars = list(data)


data = [list(z) for z in zip(citys, city_stars)]

生产热点地图

geo = (
    Geo()
    .add_schema(maptype="china")
    .add(
        "热点图",    #图题
        data,
        type_=ChartType.HEATMAP,   #地图类型
    )
    .set_series_opts(label_opts=opts.LabelOpts(is_show=False))  #设置是否显示标签
    .set_global_opts(
            visualmap_opts=opts.VisualMapOpts(max_ = 5000),    #设置legend显示的最大值
            title_opts=opts.TitleOpts(title=""),   #左上角标题
    )
)

geo.render_notebook()  #notebook渲染
# geo.render('geo.html')   #输出到html文件

生成柱状图

from pyecharts.charts import Bar
data.sort(key=lambda x:x[1], reverse=True)
xaxis=[]
yaxis=[]
for x in range(15):
    xaxis.append(data[x][0])
    yaxis.append(data[x][1])


bar1=(
      Bar() ##定义为柱状图
      .add_xaxis(xaxis) ##X轴的值
      .add_yaxis(' TOP 15 的热点旅游城市',yaxis) # #y的值和y的一些数据配置项
      )

# bar1.render('bar1.html') ###输出html文件
bar1.render_notebook()

生产饼图

from pyecharts.charts import Pie
data3 = df.groupby(by=['name'])['star'].sum()
names = list(data3.index)
name_stars = list(data3)

data3 = [list(z) for z in zip(names, name_stars)]
data3.sort(key=lambda x:x[1], reverse=True)

pie = Pie()
pie.add('',data3[:10])
pie.render_notebook()

参考内容:
派森酱 Python技术
国庆长假已结束,Python 告诉你 6 亿国人都去哪儿浪了
https://mp.weixin.qq.com/s?__biz=MzU1NDk2MzQyNg==&mid=2247487266&idx=1&sn=92d02eb0f2df53c51e0e0f4f2cd46f8c&chksm=fbdad7afccad5eb93a02078e2d4d5f45c0f97cf42e7135ea48e8ea53368191fecce52c22733d&mpshare=1&scene=24&srcid=10153ctZQzo4fyh4jnEHx2AN&sharer_sharetime=1602722052425&sharer_shareid=abd304ffaea8615085d6442028d05fe0&key=e8ca14f203d03fdf0f8b23aa05c8e727948b689287899b9bdbc006c2574ae439ddee54703885d6cdd9fe43af271e861c1bf8795440c8ca5aef6e088a6a28d3e8ca4b3b31e9e45f8907492fb2ac4864bafe357bc01f59839cae2f92e17472cf58c3dcad2c69120dfe462add9ea8b3b8d621e58df5ab18d7731dd71a8577826072&ascene=14&uin=ODc0MjY5NTYw&devicetype=Windows+10+x64&version=6300002f&lang=zh_CN&exportkey=AY6rXYsuA6oc10AEcDOwhQg%3D&pass_ticket=Xc38Umcst%2FPXfT6SzFtfTBDpa52NEIqYVyDtD6lTCvkWRk5jlqFmAz5sjuWYhRAo&wx_header=0

posted on 2020-11-02 09:01  耀扬  阅读(187)  评论(0编辑  收藏  举报

导航