栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Python抓取全国旅游景点以及小吃数据,想做旅游攻略?Python助你事半功倍。

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python抓取全国旅游景点以及小吃数据,想做旅游攻略?Python助你事半功倍。

前言

        疫情自从来了之后已经很久没有出去旅游过了,蹭着这段疫情好转,那肯定是要出去走一走的,这一篇其实是全国旅游中的一站,因为每个城市能玩的地方太多了,一篇文章下来肯定是写不了的,所以今天就抓取一下——兰州。如果大家喜欢这个案例的话  后续会陆续更新的。

兰州

摘录一段来自维基百科中关于兰州的简介:

兰州市,简称 兰 ,别称 金城 ,是 中华人民共和国 甘肃省 省会,国务院批复确定的中国西北地区重要的工业基地和综合交通枢纽,丝绸之路经济带的重要节点城市,西部地区重要的中心城市之一,西北地区第三大城市,“兰州—西宁城市群”中的核心城市,位于甘肃省中部。

下面是兰州的行政区域:

爬取信息

爬取的信息主要是兰州的美食和景点信息:

import pandas as pd
import re
import csv
import json
import requests
import random


# 显示所有列
pd.set_option('display.max_columns', None)

# 显示所有行
pd.set_option('display.max_rows', None)

# 设置value的显示长度为100,默认为50
pd.set_option('max_colwidth',100)

# 绘图相关
import jieba
import matplotlib.pyplot as plt
from pyecharts.globals import CurrentConfig, OnlineHostType   # 事先导入,防止不出图
from pyecharts import options as opts  # 配置项
from pyecharts.charts import Bar, Scatter, Pie, Line, HeatMap, Funnel, WordCloud, Grid, Page  # 各个图形的类
from pyecharts.commons.utils import JsCode   
from pyecharts.globals import ThemeType,SymbolType

 

景点爬取

下面单页爬取的代码,采用的是正则爬取的方式:

url = "https://travel.qunar.com/p-cs300026-lanzhou-jingdian-1-1"

headers = {"user-agent": "个人请求头"}

response = requests.get(url=url,headers=headers)
result = response.content.decode()

如果解析的HTML源码中含有双引号,那么re.findall()方法后面的字符串的最外层使用单引号

In [3]:

# 1-景点中文名称

cn_title = re.findall('>(.*?).*?',result,re.S)
print("长度:",len(cn_title))
cn_title
长度: 10

Out[3]:

['甘肃省博物馆',
 '黄河铁桥',
 '白塔山公园',
 '黄河母亲雕塑',
 '兰州新区长城影视基地',
 '石佛沟国家森林公园',
 '黄河索道',
 '五泉山公园',
 '兰州极地海洋世界',
 '兰山公园']

In [4]:

# 2-景点英文名称

en_title = re.findall('(.*?).*?',result,re.S)
print("长度",len(en_title))
en_title
长度 10

Out[4]:

['Gansu Provincial Museum',
 'Yellow River Steel Bridge',
 'Baitashan Park',
 'Yellow River Mother Sculpture',
 'Lanzhou Xinqu Changcheng Yingshi Base',
 'Lanzhou Shifo Valley National Forest Park',
 'Huanghe Ropeway',
 'Wuquanshan Park',
 'Lanzhou Ocean World',
 'Lanshan Park']

In [5]:

# 3-strategy攻略数量
strategy = re.findall(' title="攻略">(.*?)',result, re.S)
print(len(strategy))
strategy
10

Out[5]:

['50', '94', '40', '35', '0', '1', '3', '2', '0', '1']

In [6]:

# 4-comment点评数量

comment = re.findall(' title="点评">(.*?)',result, re.S)
print(len(comment))
comment
10

Out[6]:

['1295', '2948', '793', '489', '23', '30', '46', '354', '146', '80']

In [7]:

# 5-景点地点(长沙景点排名、宁乡景点排名等)
# 我们只需要"景点排名"之前的信息,代表的是地址

location = re.findall('去过(.*?)的驴友', result, re.S)
print(len(location))
location
10

Out[7]:

['兰州', '兰州', '兰州', '兰州', '永登', '兰州', '兰州', '兰州', '兰州', '兰州']

In [8]:

# 6-景点排名

ranking = re.findall('.*?>(.*?)',result,re.S)
print(len(ranking))
ranking
10

Out[8]:

['7', '3', '11', '10', '0%', '56', '1', '17', '5', '49']

In [9]:

# 7-驴友
# 有多少的驴友也去过这个地方

lvyou = re.findall('>.*?>(.*?)',result,re.S)
print(len(lvyou))
lvyou
10

Out[9]:

['35%', '58%', '30%', '30%', '0%', '0%', '0%', '1%', '0%', '1%']

In [10]:

# 8-景点简介
abstract = re.findall('>(.*?)',result,re.S)
print(len(abstract))
abstract
10

Out[10]:

['通过丰富精彩的展品了解古丝绸之路、唐蕃古道上多民族的文化和历史。',
 '兰州市最为经典的地标建筑,夜晚时铁桥彩灯闪耀,周围夜景非常漂亮。',
 '登上山顶可以俯瞰壮观的兰州城市全景,山间建筑古朴树木众多,让人感受舒心惬意。',
 '黄河母亲雕塑现已经成为兰州的标志性雕塑,也代表着兰州形象。',
 '',  # 空值
 '',
 '',
 '公园景点以五眼名泉和佛教古建筑为主,园内丘壑起伏,林木葱郁,环境清幽。',
 '',
 '公园就位于山顶制高点上,可俯瞰兰州全景。']

最终爬取的结果:

美食爬取

单页信息爬取的代码,同样是基于正则表达式的爬取:总共是200页

In [2]:

url = "https://travel.qunar.com/p-cs300026-lanzhou-meishi?page=1"
headers = {"user-agent": "个人请求头"}
response = requests.get(url=url,headers=headers)
result = response.content.decode()

cn_title

In [3]:

cn_title = re.findall('cn_tit">(.*?).*?countbox',result,re.S)

In [4]:

print(len(cn_title))
cn_title
10

Out[4]:

['正宁路小吃夜市',
 '安泊尔牛肉面(北滨河路店)',
 '兰州大众巷美食街',
 '马三洋芋片(兰州总店)',
 '清真·马安军辣子牛肉面',
 '安泊尔',
 '杜记甜食',
 '孙子烤肉(皋兰路店)',
 '大漠烤肉(盘旋路店)',
 '清真•白建强牛肉面']

score

In [5]:

score = re.findall('cur_score">(.*?).*?total_score',result,re.S)

In [6]:

print(len(score))
score
10

Out[6]:

['4.3', '4.5', '--', '4.3', '3.5', '5.0', '4.2', '3.5', '4.2', '0.0']

sublistbox

先提取整个sublistbox,然后对里面的每个子元素单独提取

In [7]:

sublistbox = re.findall('sublistbox">(.*?)', result, re.S)

sublistbox[:1]

Out[7]:

['
人u3000均
¥ 63
地u3000址
白银路街道永昌南路正宁路
推荐菜
当地口味t美食街t老字号t深夜营业
吃客云集的小吃街,地道吃食令人回味。']

In [8]:

type(sublistbox)

Out[8]:

list

In [9]:

# 对sublistbox单独提取

均价

In [10]:

person_avg = []

for i in range(len(sublistbox)):
    try:
        if "均" in sublistbox[i]:
            person_avg.append(re.findall('¥ (.*?)',sublistbox[i],re.S)[0])
        else:
            person_avg.append(0)
        continue
    except:
        person_avg.append(0)

In [11]:

print(len(person_avg))
person_avg
10

Out[11]:

['63', '27', 0, '19', '17', 0, '14', '58', '58', '18']

地址

In [12]:

address = []

for i in range(len(sublistbox)):
    try:
        if "址" in sublistbox[i]:
            address.append(re.findall('址.*?des_line">(.*?)',sublistbox[i],re.S)[0])
        else:
            address.append("无")
        continue
    except:
        address.append("无")

In [13]:

print(len(address))
address
10

Out[13]:

['白银路街道永昌南路正宁路',
 '北滨河路754号(龙源斜对面)',
 '兰州市城关区大众巷',
 '通渭路79号',
 '七里河北街忠云宾馆斜对面',
 '北滨河路金城关3号',
 '大众巷72号',
 '皋兰路4号(虹云宾馆北侧)',
 '东岗西路451号',
 '雁滩路3423号']

推荐菜

In [14]:

recommand = []

for i in range(len(sublistbox)):
    try:
        if "推荐菜" in sublistbox[i]:
            recommand.append(re.findall('推荐菜.*?des_line">(.*?)',sublistbox[i],re.S)[0])
        else:
            recommand.append("无")
        continue
    except:
        recommand.append("无")

In [15]:

print(len(recommand))
recommand
10

Out[15]:

['当地口味t美食街t老字号t深夜营业',
 '美食林风味t当地口味t肉汤萝卜t三泡台t酱牛肉t蜂蜜油香t安泊尔牛肉面t牛筋t雪梨汤t牛腱子肉t甜醅子t灰豆子',
 '马子禄牛肉面t香满楼t俊杰羊肉泡馍馆t杜维成甜食店',
 '美食林风味t当地口味t炸年糕t里脊肉饼t洋芋片t年糕t辣年糕t胡萝卜汁t豆腐皮t油炸年糕t炸糖年糕t胡萝卜素饮料t豆皮t牛肚',
 '无',
 '无',
 '当地口味t下午茶t老字号t美食林风味t高担酿皮t甜胚子t牛肉馅饼t粽子t八宝醪糟t炒粉t茹记杏皮水t热晶糕t甜醅子t牛奶鸡蛋醪糟t甜醅t灰豆子',
 '无',
 '深夜营业t美食林臻选t羊腰t凉面t烤羊肚t羊汤t羊肉泡馍t烤羊排t烤饼t烤羊板筋t烤肉串t烤羊皮t杏皮水t烤茄子',
 '特色小吃t当地口味t其他t兰州拉面t牛肉面t牛肉']

评价

In [16]:

comment = []

for i in range(len(sublistbox)):
    try:
        if "desbox" in sublistbox[i]:
            comment.append(re.findall('.*?txt">(.*?)',sublistbox[i],re.S)[0])
        else:
            comment.append("无")
        continue
    except:
        comment.append("无")

In [17]:

print(len(comment))
comment
10

Out[17]:

['吃客云集的小吃街,地道吃食令人回味。',
 '专注正宗牛肉面,开放式厨房热气腾腾',
 '大众巷是兰州最古老的美食街,拥有许多老字号当地特色美食,是游客体验兰州美食文化的绝佳去处。',
 '兰州代表性的小吃店,明档操作干净放心',
 '颇具名气的牛肉面馆,当地人的家庭食堂',
 '个人觉得安泊尔是我吃过最好吃的牛肉面了,不过这家店的位置很尴尬,只有这趟路线才能涉及到',
 '老牌人气甜食店,荣获多个美食奖项',
 '店里面的装修环境是非常不错的,有人说价格有点贵,看了一下菜单,相对于夜市上的来说确实有一点贵,...',
 '人气爆棚的口碑餐厅,各式烤串喷香诱人',
 '当地食堂级别的老店,牛肉面汤清味醇面韧。']

最终爬取结果:刚好是2000条数据

下面是对上面爬取到的两份数据进行分析:

美食数据分析

导入数据:

字段基本信息:

In [3]:

# 1-数据缺失值

df.isnull().sum()

Out[3]:

中文名    0
得分     0
均价     0
地址     0
推荐菜    0
评价     0
dtype: int64

In [4]:

# 2、字段类型

df.dtypes

Out[4]:

中文名    object
得分     object
均价      int64
地址     object
推荐菜    object
评价     object
dtype: object

分析哪些店的得分靠前:

In [5]:

# 得分中有未评分的数据:--

df["得分"].value_counts()

Out[5]:

--     1721
3.5     139
3.0      50
4.0      29
4.5      20
5.0      13
4.3       7
4.2       6
0.0       5
4.1       4
2.0       2
3.8       1
4.7       1
2.5       1
1.0       1
Name: 得分, dtype: int64

In [6]:

# 将未评分的数据统一替换成0.0,也就是0分

df["得分"] = df["得分"].apply(lambda x: x.replace("--","0.0"))
得分统计

大部分店铺的得分在3.5分,好像并不是很高~

得分前10的店铺

店铺均价占比

高档餐厅

面馆

到了兰州肯定得吃面:据数据统计有284家面馆

火锅店

统计出来有129家火锅店:

px.bar(huoguo[:15],x="中文名",y="得分")

美食统计信息

推荐菜词云

绘制当地推荐菜的词云图:

rec_words = [tuple(z) for z in zip(result["词语"].tolist(), result["次数"].tolist())]

# 选择前100个词语

c = (
    WordCloud(init_opts=opts.InitOpts(theme=ThemeType.CHALK)) 
    .add("", rec_words[:100], word_size_range=[20, 80], shape=SymbolType.DIAMOND)
    .set_global_opts(title_opts=opts.TitleOpts(title="兰州美食词云图"))
)

c.render_notebook()

景点数据分析

还是先导入数据

数据探索

In [3]:

df1.shape

Out[3]:

(381, 8)

In [4]:

df1.isnull().sum()

Out[4]:

cn_title      0
en_title    113
strategy      0
comment       0
location      0
ranking       0
lvyou         0
abstract    351
dtype: int64

在景点的英文名en_title和简介abstract中存在缺失值

In [5]:

df1.dtypes

Out[5]:

cn_title    object
en_title    object
strategy     int64
comment      int64
location    object
ranking      int64
lvyou       object
abstract    object
dtype: object
景点位置分布

In [6]:

df2 = df1["location"].value_counts().reset_index()
df2.columns = ["location","number"]
df2

Out[6]:

locationnumber
0兰州301
1永登39
2皋兰21
3榆中20

In [7]:

c = (
    Pie(init_opts=opts.InitOpts(theme=ThemeType.CHALK))
    .add("", [list(z) for z in zip(df2["location"].tolist(), df2["number"].tolist())])
    .set_global_opts(title_opts=opts.TitleOpts(title="兰州景点分布"),
                    legend_opts=opts.LegendOpts(pos_left="80%", orient="vertical"))
    .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
)

c.render_notebook()

攻略数

评论数前10名
c = (
    Funnel(init_opts=opts.InitOpts(theme=ThemeType.CHALK,
                                   width="800px",
                                   height="500px"
                                  ))
    .add("兰州景点评论数漏斗", [list(z) for z in zip(df5["cn_title"].tolist(), df5["comment"].tolist())])
    .set_series_opts(label_opts=opts.LabelOpts(is_show=True)) 
)

c.render_notebook()

景点词云

前50个词语的展示:

rec_words = [tuple(z) for z in zip(result["词语"].tolist(), result["次数"].tolist())]

c = (
    WordCloud(init_opts=opts.InitOpts(theme=ThemeType.ROMA))
    .add("", rec_words[:50], word_size_range=[20, 80], shape=SymbolType.DIAMOND)
    .set_global_opts(title_opts=opts.TitleOpts(title="兰州景点词云"))
)

c.render_notebook()

整体绘图
# 1-景点位置

def piePage() -> Pie:
    c = (
    Pie(init_opts=opts.InitOpts(theme=ThemeType.CHALK))
    .add("", [list(z) for z in zip(df2["location"].tolist(), df2["number"].tolist())])
    .set_global_opts(title_opts=opts.TitleOpts(title="兰州景点分布"),
                    legend_opts=opts.LegendOpts(pos_left="80%", orient="vertical"))
    .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}")))

    return c

# 2-攻略数

def barPageOne() -> Bar:
    c = (
    Bar(init_opts=opts.InitOpts(theme=ThemeType.CHALK))
    .add_xaxis(df4["cn_title"].tolist()[::-1])
    .add_yaxis("攻略数", df4["strategy"].tolist()[::-1])
    .reversal_axis()   #  翻转坐标轴
    .set_series_opts(label_opts=opts.LabelOpts(is_show=True, position="right"))   # 是否显示数据以及label的位置(显示在右方)
    .set_global_opts(title_opts=opts.TitleOpts(title="兰州景点攻略数前10"))
    )
    return c

# 3-评论数
def funnlePage() -> Funnel:
    c = (
    Funnel(init_opts=opts.InitOpts(theme=ThemeType.MACARONS,
                                   width="800px",
                                   height="600px"
                                  ))
    .add("兰州景点评论数漏斗", [list(z) for z in zip(df5["cn_title"].tolist(), df5["comment"].tolist())])
    .set_series_opts(label_opts=opts.LabelOpts(is_show=True)))
    
    return c


# 4-驴友占比

def barPageTwo() -> Bar:
    c = (
    Bar(init_opts=opts.InitOpts(theme=ThemeType.WALDEN))
    .add_xaxis(df6["cn_title"].tolist())
    .add_yaxis("", df6["lvyou_number"].tolist())
#     .reversal_axis()   #  翻转坐标轴
    .set_series_opts(label_opts=opts.LabelOpts(is_show=True))   # 是否显示数据以及label的位置(显示在右方)
    .set_global_opts(title_opts=opts.TitleOpts(title="兰州景点驴友占比"),
                     xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-30)),  # 设置旋转角度
                    ))
    return c



# 5-词云图
def worldPage() -> WordCloud:
    rec_words = [tuple(z) for z in zip(result["词语"].tolist(), result["次数"].tolist())]

    c = (
        WordCloud(init_opts=opts.InitOpts(theme=ThemeType.ROMA))
        .add("", rec_words[:50], word_size_range=[20, 80], shape=SymbolType.DIAMOND)
        .set_global_opts(title_opts=opts.TitleOpts(title="兰州景点词云"))
    )

    return c

page = (
    Page(layout=Page.DraggablePageLayout)
    .add(
        piePage(),
        barPageOne(),
        funnlePage(),
        barPageTwo(),
        worldPage()
))

page.render("lanzhou.html")

需要完整项目代码关注下方 公众号:Python源码

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1008198.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号