这次是收集一些感兴趣的POI在各个城市的分布,以及信息。由于百度API的特质,一次最多能返回400个信息,所以就需要将整个城市做一个分割,然后分块获取信息。具体的代码如下:
from urllib import request
import pandas as pd
import numpy as np
import urllib.parse as urp
import time
import json
##分块的代码是之前负责这个工作的实习生小朋友留下的,我就直接拿来用了。
def getArea(loc_1,loc_2,step):
#步长根据测试选择相对合适的值
#for循环嵌套,获取loc_2与loc_1间步长0.03的矩形区域列表
loc_fin = []
for a in range(1,int((loc_2[0]-loc_1[0])/step+1)+1):
for b in range(1,int((loc_2[1]-loc_1[1])/step+1)+1):
lat_1 = round((loc_1[0]+step*a),6)
lon_1 = round((loc_1[1]+step*b),6)
lat_2 = round((lat_1-step),6)
lon_2 = round((lon_1-step),6)
loc_fin.append(str(lat_2)+","+str(lon_2)+','+str(lat_1)+','+str(lon_1))
df = pd.DataFrame({'loc':loc_fin,'id':np.arange(len(loc_fin))})
return df
class PoiInfo:
def __init__(self,data,target):#初始化需要给PoiInfo这个类一个坐标列表,也就是各个小区域的坐标范围,还有你要获取POI的类别
self._df = data
self._df_final = pd.DataFrame([],columns = ['name','area','address',\
'lng','lat','price','com_num','key_word',\
'tag','type','children'])
self._t = target
self._miss_index = []
def _getjson(self,url):
req = request.urlopen(url)
res = req.read().decode()
result = json.loads(res)
return result
def geturl(self,pos,page_num):
my_ak = ##替换上自己的AK
url = 'http://api.map.baidu.com/place/v2/search?query='+urp.quote(self._t)+\
'&bounds='+self._df.loc[pos,'loc']+'&output=json&scope=2&page_size=20&page_num='+\
str(page_num)+'&ak='+my_ak
return url
def _get_pub_info(self,r2):##这个函数是获取所有类别都需要的公共信息,比如名字地址和坐标
name = r2.apply(lambda x:x['name'])
address = r2.apply(lambda x:x['address'])
lat = r2.apply(lambda x:x['location']).apply(lambda x:x['lat'])
lng = r2.apply(lambda x:x['location']).apply(lambda x:x['lng'])
return name,address,lat,lng
def _getrating(self,detail):##之后的一系列函数都是为了避免返回值中没有这些信息,所以用了try...except
try:
return detail['overall_rating']
except:
return np.nan
def _getchild(self,detail):
try:
return detail['childeren']
except:
return np.nan
def _getcom_num(self,detail):
try:
return detail['comment_num']
except:
return np.nan
def _getword(self,detail):
try:
return detail['di_review_keyword']
except:
return np.nan
def _gettag(self,detail):
try:
return detail['tag']
except:
return np.nan
def _gettype(self,detail):
try:
return detail['type']
except:
return np.nan
def _getprice(self,detail):
try:
return detail['price']
except:
return np.nan
def getinfo(self):
for i in self._df.index:
time.sleep(2)
print(i)
try:
temp_df = pd.DataFrame([],columns = ['name','area','address',\
'lng','lat','price','com_num','key_word',\
'tag','type','children','rating'])
url = self.geturl(i,0)
result = self._getjson(url)
total = result['total']
if total > 0:
for j in np.arange(0,int(total/20)+1):
print('...working on it...')
try:
url = self.geturl(i,j)
time.sleep(2)
r1 = self._getjson(url)
r2 = pd.Series(r1['results'])
name,address,lat,lng = self._get_pub_info(r2) ##获取公共信息,存在temp_df中
temp_df['name'] = name
temp_df['address'] = address
temp_df['lat'] = lat
temp_df['lng'] = lng
if (self._t == '商场')|(self._t=='中学')|(self._t=='小学')|(self._t=='超市')|\ ##遇到这些类别时候,获取
(self._t == '地铁站'):##区域和城市
area = r2.apply(lambda x:x['area'])
temp_df['area'] = area
city = r2.apply(lambda x:x['city'])
temp_df['city'] = city
if (self._t == '商场')|(self._t == '美食')|(self._t ==\##遇到这些类别时候获取这些信息
'电影院')|(self._t=='超市'):
tag = r2.apply(lambda x:x['detail_info']).apply(self._gettag)
temp_df['tag'] = tag
if (self._t == '美食') | (self._t == '电影院'):
temp_df['rating']=r2.apply(lambda x:x['detail_info']).\
apply(self._getrating)
# temp_df['price'] = r2.apply(lambda x:x['detail_info']).\
#apply(self._getprice)
self._df_final = self._df_final.append(temp_df,ignore_index=True)##将收集到的信息append到总表中
except:
self._miss_index.append(i)##如果报错记录下self._df中哪些index被跳过了
break
except:
print('aho')
self._miss_index.append(i)
return self._df_final
def get_ori_data(self):
return self._df_final
def get_miss(self):
return self._miss_index
为了防止断开连接,所以每一百个区域跑一次,跑完之后把数据清理一下。
data1 = pd.read_excel('深圳超市1.xlsx')
data2 = pd.read_excel('深圳超市2.xlsx')
data3 = pd.read_excel('深圳超市3.xlsx')
data4 = pd.read_excel('深圳超市4.xlsx')
data5 = pd.read_excel('深圳超市5.xlsx')
data6 = pd.read_excel('深圳超市6.xlsx')
df = (data1.append(data2,ignore_index=True)).append(data3,ignore_index=True).\
append(data4,ignore_index=True).append(data5,ignore_index=True)\
.append(data6,ignore_index=True)
data = (df[~pd.isnull(df['name'])].drop(['children','com_num','price','rating','type','key_word'],axis = 1))\
.reset_index(drop = True)
这里面有一些垃圾数据,比如一些instances不是超市,所以我在收集信息的时候把tag收集到了。这里面会可以作为判断是不是
垃圾信息的条件。
data['tag'].value_counts()
购物;便利店 15352 购物;超市 9695 购物;商铺 1916 购物;市场 320 购物 311 购物;其他 193 购物;家居建材 151 购物;购物中心 87 公司企业;公司 67 购物;家电数码 45 生活服务;家政服务 31 美食;小吃快餐店 25 购物;集市 18 美食;中餐厅 17 生活服务;物流公司 17 美食;蛋糕甜品店 15 房地产;内部楼栋 13 生活服务 12 房地产;住宅区 12 美食 11 房地产;其他 10 生活服务;其他 9 生活服务;公用事业 8 生活服务;维修点 7 房地产;写字楼 6 公司企业 6 丽人;美发 5 运动健身;体育场馆 4 生活服务;通讯营业厅 4 教育培训;培训机构 4 ... 文化传媒;展览馆 2 医疗;药店 2 休闲娱乐;农家院 2 丽人 2 汽车服务;汽车美容 2 公司企业;厂矿 2 生活服务;照相馆 2 公司企业;农林园艺 2 酒店;其他 2 休闲娱乐;网吧 2 门址;门址点 2 交通设施;停车场 1 交通设施;长途汽车站 1 道路 1 政府机构;福利机构 1 汽车服务 1 教育培训;中学 1 教育培训;其他 1 休闲娱乐;剧院 1 休闲娱乐;歌舞厅 1 汽车服务;汽车销售 1 美食;咖啡厅 1 汽车服务;汽车维修 1 医疗;其他 1 医疗 1 房地产 1 金融;atm 1 教育培训;科研机构 1 旅游景点;风景区 1 休闲娱乐;ktv 1 Name: tag, Length: 74, dtype: int64
可以看到很多信息的tag并不是超市或者便利店。所以我选择tag包含超市或者便利店的
data[(data['tag'].str.contains('超市'))|(data['tag'].str.contains('便利店'))].head()
address | area | city | lat | lng | name | tag | |
---|---|---|---|---|---|---|---|
0 | 广东省深圳市南山区赤湾海景大厦西(赤湾四路南) | 南山区 | 深圳市 | 22.485020 | 113.893785 | 佳惠生活超市 | 购物;超市 |
1 | 深圳市南山区 | 南山区 | 深圳市 | 22.479409 | 113.886283 | 一米阳光 | 购物;超市 |
2 | 赤湾二路6 | 南山区 | 深圳市 | 22.484467 | 113.892684 | 赤湾加油站-便利店 | 购物;便利店 |
3 | 深圳市南山区赤湾四路44号 | 南山区 | 深圳市 | 22.484526 | 113.890047 | 海景商店 | 购物;便利店 |
4 | 深圳市南山区赤湾七路6 | 南山区 | 深圳市 | 22.484872 | 113.894957 | 赤湾振兴商店 | 购物;便利店 |