Python爬取美团数据并使用数据做相关的美食网站

本文由数据的获取(采用Python爬虫)、数据的分析、数据的展示三个主要的方面组成,最后以网站的形式展示出数据分析的结果,使目标用户(消费者和商家)能够更方便、快捷的了解到自己所需要的美食相关信息,进而做出相应的决定。

本文主要针对以下功能模块进行设计和实现:Python爬虫数据爬取和数据分析

爬虫架构

在文章开始之前,我们先了解一下爬虫的架构,以便对爬虫有更好的理解。

本系统采用的爬虫为简单的聚焦爬虫,给定爬虫程序初始的URL,程序获得初始URL,按广度优先的策略选取初始URL进行爬取,在抓取网页的过程中,有选择的爬取新的有用URL放入队列,直到满足系统的一定停止条件。然后从队列中按先进先出的规则选择下一步要抓取的网页URL,对爬取的网页进行分析,提取出所需要的信息,进而保存到本地数据库。下图为简单爬虫架构图

img

爬虫调度端:启动爬虫、停止爬虫、监视爬虫的运行情况

1) URL管理器:管理将要爬取的URL和已经爬取的URL。将待爬取的URL传送给网页下载器。

2) 网页下载器:将URL指定的网页下载下来,保存为一个字符串。将这个字符串传送给网页解析器进行解析。

3) 网页解析器:一方面,会解释出有价值的数据;另一方面,解析出字符串中的URL,将其补充到URL管理器。

三个模块,形成了一个循环。只要有未爬取的URL,这个循环就会一直继续下去。

Python爬取美团获取数据

![img](http://or4kgmiww.bkt.clouddn.com/222.png)img

确定目标

​ 本项目要爬取的目标为美团网北碚区的页面,以及所有相关的商家信息的页面。

分析目标

确定网页的URL格式

​ 首先打开我们的目标网站进行分析:

![img](http://or4kgmiww.bkt.clouddn.com/222.png)img

​ 目标网站有多个页面,通过多次的页面切换以及URL删减,发现有用的URL格式为:http://beipei.meituan.com/category/meishi/all/pagex。其中x的值为1到6,表示第一页到第六页。

​ 因为我们要爬取的是每个商家的具体信息,所以需要进到每个商家的具体页面中去爬取有用的数据进行保存,因此,我们右键每个店铺的链接,审查元素:

![img](http://or4kgmiww.bkt.clouddn.com/222.png)img

​ 对多个商家的链接进行审查元素可以发现,每个商家的URL位于<aclass=”link f3 J-mtad-lin”>标签中,因此我们只要匹配该标签中的href属性即可得到每个商家的入口URL。通过对每个商家的URL进行分析可以发现商家的URL格式为:http://beipei.meituan.com/shop/x。其中x为商家的店铺号。

​ 由于美团网的网页采用了异步加载技术——也就是需要我们将鼠标滑动到网页底部网页才会加载更多的商家信息,所以如果直接对入口地址中的商家URL信息进行采集的话是无法爬取到所有的商家信息的。因此我们对入口地址进行审查元素,查看其在后台提交的数据:

![img](http://or4kgmiww.bkt.clouddn.com/222.png)img

​ 通过使用POSTMAN模拟提交该POST请求可以发现:请求中的poiidList数组中包含着本次请求的所有商家的店铺号,而网页给出的相应则是所有店铺号的商家信息。而对该网页继续往下浏览可以发现,该网页一共提交了多个该POST请求,每次请求的poiidList数组中都含有新的商家店铺号。因此我们需要在入口地址网页中查找该poiidList数组,获得其中所有的店铺号:

![img](http://or4kgmiww.bkt.clouddn.com/222.png)img

​ 在网页源码中搜索poiidList,得到了一个结果,正是保存所有商家店铺号的数组。因此,我们只需要在该网页中匹配得到该数组,再加上商家URL的前缀即可得到所有商家的URL地址。

确定要采集的数据格式

​ 进入具体的商家页面,以爬取商家的名字为例,对商家名右键审查元素:

![img](http://or4kgmiww.bkt.clouddn.com/222.png)img

​ 通过审查元素可以发现,商家名是位于标签中的文本,因此我们只要匹配该标签就能得到商家名的信息。对要采集的其他商家信息(如地理位置、评价人数等)也是采用相同的方法对其进行审查,得到相应的数据格式。

确定网页的编码

​ 在网页的任意地方右键,审查元素,我们可以发现,网页的编码格式为utf-8:

![img](http://or4kgmiww.bkt.clouddn.com/222.png)img

对分析目标的结果进行总结可以得到如下的抓取策略:

目标:美团网北碚区所有商家的美食信息—商家名、地理位置、分类、评分、评价人数、URL、起价、服务、图片
入口页:http://beipei.meituan.com/category/meishi/all/page1
URL格式:商家页面URL:http://cq.meituan.com/shop/1093172
数据格式:商家名:<span *** class=”title”>商家名
页面编码:utf-8

编写代码

​ 根据目标分析的结果结合如下爬虫运行流程编写相应的爬虫程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#导入要用到的相关包
import requests
import re
import urllib
import xlwt
import time
from bs4 import BeautifulSoup
from xlwt import *
from hmac import new
from xlwt import Workbook
from asyncio.tasks import sleep
import pymysql.cursors

#保存结果的字典
shopinfos = {}
shopinfos['urls']=[]
shopinfos['name']=[]
shopinfos['weizhi']=[]
shopinfos['fenlei']=[]
shopinfos['pingfen']=[]
shopinfos['pingjiarenshu']=[]
shopinfos['tupian']=[]
shopinfos['zhichifuwu']=[]
shopinfos['qijia']=[]

#获取网页的源码信息
def getHtml(url):
headers = ('User-Agent',
'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11')
opener = urllib.request.build_opener()
opener.addheaders = [headers]
htmldata = opener.open(url).read()
htmldata=htmldata.decode('utf-8')
return htmldata

#changepage用来生产不同页数的链接
def changepage(url,total_page):
now_page = int(re.search('page(\d+)',url,re.S).group(1))
page_group = []
for i in range(now_page,total_page+1):
link = re.sub('page\d+','page%s?mtt=1'%i,url,re.S)
page_group.append(link)
return page_group

def getImg(url,i):
#将图片写入本地
f=open(r"d:\123"+'/'+str(i)+'.jpg','wb')
req=urllib.request.urlopen(url)
buf=req.read()
f.write(buf)


#开始执行程序
if __name__ == '__main__':
#入口URL
url = 'http://beipei.meituan.com/category/meishi/all/page1'
#计数器
i=0
#匹配生成6页入口URL
urldic = changepage(url,6)
#用于正则匹配poiidList数组
reg=r'(?<=\"poiidList\\":\[).+?(?=\])'
ur=re.compile(reg)

#抓取所有商家的URL
for url in urldic:

data = getHtml(url)

soup=BeautifulSoup(data,'html.parser')

aa=soup.select('div[class="J-scrollloader cf J-hub"]')[0].get('data-async-params')
uurls=ur.search(soup.select('div[class="J-scrollloader cf J-hub"]')[0].get('data-async-params'))
tempurls=uurls.group(0)
x=""
for i in tempurls:

if( i!=','):
x=x+i
else:

fen_url="http://cq.meituan.com/shop/"+x
x=""
shopinfos['urls'].append(fen_url)
shopinfos['urls'].append(fen_url)

#连接mysql数据库
connect = pymysql.Connect(
host='localhost',
port=3306,
user='root',
passwd='1234567',
db='meishi',
charset='utf8'
)
#创建游标
cursor = connect.cursor()
#创建两个SQL语句,用于查询和插入
sql_charu = "INSERT INTO beibei (name, weizhi, fenlei,pingfen,qijia,fuwu,pingjiarenshu,tupian,url) VALUES ( '%s', '%s', '%s', '%s',%.1f, '%s',%d,%d, '%s' )"
sql_chazhao="SELECT * FROM beibei WHERE url = '%s' "
i=0
num=0
#从每个URL中采集商家信息
for url_temp in shopinfos['urls']:
#如果该URL已经爬取过,则忽略
cursor.execute(sql_chazhao % url_temp)
if cursor.fetchall():
continue
#为避免被反爬虫机制检测,暂停一定时间
if num%10==0:
time.sleep(5)
data = getHtml(url_temp)
#采用BeautifulSoup采集源码匹配内容
soup=BeautifulSoup(data,'html.parser')
tus=soup.select('span[class="img-wrapper"] img')
namee=(soup.select('div[id="bd"] div[class="summary biz-box fs-section cf"] div[class="fs-section__left"] h2 span[class="title"]'))
weizhi_temp=(soup.select('div[id="bd"] div div[class="fs-section__left"] p span[class="geo"]'))
pinfen=(soup.select('div[id="bd"] div div[class="fs-section__right"] div div span[class="biz-level"]'))
fenlei_temp=(soup.select('div[class="info"] div a'))
fuwu_temp=(soup.select('div[class="field-group"]'))
renshu=(soup.select('div[id="bd"] div div[class="fs-section__right"] div div a[href="#evaluate-section"]'))
jiages_temp=soup.select('div[id="anchor-salelist"] ul li span span em strong')
#所有信息全都匹配成功,则保存
if tus and namee and weizhi_temp and pinfen and fenlei_temp and fuwu_temp and renshu and jiages_temp:
mat=tus[0].get('src')
#为避免被反爬虫机制检测,暂停一定时间
if i%20==0:
time.sleep(10)
#保存图片到本地
getImg(mat,i)
i+=1
shopinfos['tupian'].append(mat)
#保存商家名
name=namee[0].get_text()
shopinfos['name'].append(name)
#保存商家位置
weizhi=weizhi_temp[0].get_text()
shopinfos['weizhi'].append(weizhi)
#保存商家评分
pingfen=pinfen[0].get_text()
shopinfos['pingfen'].append(pingfen)
#保存商家分类
fenlei=fenlei_temp[0].get_text()
shopinfos['fenlei'].append(fenlei)
#保存商家服务信息
fuwu=fuwu_temp[0].get_text()
shopinfos['zhichifuwu'].append(fuwu)
#保存商家评价人数
pingjiarenshu=renshu[0].get_text()
shopinfos['pingjiarenshu'].append(pingjiarenshu)
#计算商品起价并保存
jiage=9999.99
for jiages in jiages_temp:
if jiage>float(jiages.get_text()):
jiage=float(jiages.get_text())
shopinfos['qijia'].append(jiage)

#插入数据到数据库
data = (name,weizhi,fenlei,pingfen,jiage,fuwu,int(pingjiarenshu),i-1,url_temp)
cursor.execute(sql_charu % data)
connect.commit()
#控制台显示执行结果
print('成功插入', cursor.rowcount, '条数据')
print(num)
num=num+1
#关闭游标和数据库连接
cursor.close()
connect.close()

​ 编写完爬虫程序之后,运行程序,得到如下运行结果:

img

​ 导出数据库中的数据如下:

img

​ 爬取的图片保存在本地文件夹如下:

img

数据可视化分析

​ 将数据从数据库中导出到Excel表,运用Excel2016对表中的数据进行一些简单的数据分析

热力图

​ 对Excel表中的数据进行整理,然后打开Excel中的三维地图,绘制北碚区商家位置的热力图如下:

img

​ 根据该图我们可以做一些简单的分析:北碚地区美食商家最集中的地方有三处:分别是状元碑、西南大学二号门、北碚老城区。另外在重庆师范大学旁边也有较多美食商家分布,西南大学校内有着一些商家。除此之外,其余地区几乎没有商家分布。

雷达图

img

​ 通过对所有美食进行分类,然后统计出每类美食的个数,将美食以雷达图的形式呈现出来,从雷达图中可以很容易的看出各类美食商家数目的大体分布情况:火锅、川菜、小吃快餐类美食商家较多,其余类美食商家都较少。

饼状图

img

​ 从饼状图中可以很容易的看出各类美食商家所占的比例,如火锅类商家占了总商家的30%,川菜类商家占了总商家的21%。

​ 除使用Excel对数据进行可视化分析之外,还可以运用一些其他的数据可视化工具来对获取到的数据进行可视化分析(如地图无忧):

海量点图

img

分类热力图

img

​ 通过数据可视化软件对商家数据进行数据分析,我们可以得到许多有价值的信息。如我们可以清晰明了的看出商家分布的特点:状元碑、西南大学二号门、老城区、重庆师范大学外商家分布相对集中,其余地方很少有商家分布。因此如果有新商家想要开店的话,可以考虑在这些生意火爆的地区开店,当然,如果新商家不想去竞争这么激烈的地方,也可以选择现有商家较少的地方去开店;我们还可以很容易看出北碚区商家类别的分布:如火锅、川菜、小吃快餐类商家较多,其余类商家较少,这应该是与重庆人喜欢川菜、火锅有关。因此,如果有新商家想开店的话可以考虑开这几个类别的店铺,因为重庆人对这几类美食更加喜欢,开这几类店铺的话可能会有相对于其他类店铺更为火爆的生意。

网站展示

​ 将爬虫爬取的数据以及数据可视化分析的结果加以整理,最后以网站的形式呈现出来(由于间隔做这个项目的时间有点久了,所以最终的美食网站版本找不到了,这里贴出一些初期的粗糙的美食网站的图片,不喜勿喷。)。

针对消费者的数据展示

​ 网站首页简单的罗列了一些热门美食,提供美食分类查找的功能,以便用户直接查找自己喜欢的美食,并且提供了美食推荐功能。

img

​ 热门分类:用户点击自己喜欢的类(如美食自助类)则会跳转到相应类页面。

img

​ 美食推荐:点击寻找附近美食,则会跳转到美食推荐页面,根据美食的热门程度以及用户注册时选择的爱好进行相应的推荐,用户如果不喜欢则可以点击下一页换一个美食。

img

针对商家的数据分析结果展示

数据展示首页,将数据可视化分析的结果以4种不同的方式展示出来,方便商家查看,并且点击相应的标题可以放大查看可视化图片(本来是准备连接百度地图的接口实现在线可缩放的那种,后来懒也没时间就没做了)

img

​ 分类查看可视化分析的结果,如商家想开川菜类的店铺,则点击川菜跳转到川菜类分析页面

img

网站实现代码

​ 由于网站太粗糙了,所以这里就没脸贴上代码了,如果有需要的小伙伴可以在下面留言,大家如果代码有疑问或者运行起来有问题也可以留言,我看到了会进行回复(⊙o⊙)哦。