Python获取城市美食、地铁、中小学、商场及超市信息

这次是收集一些感兴趣的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()

addressareacitylatlngnametag
0广东省深圳市南山区赤湾海景大厦西(赤湾四路南)南山区深圳市22.485020113.893785佳惠生活超市购物;超市
1深圳市南山区南山区深圳市22.479409113.886283一米阳光购物;超市
2赤湾二路6南山区深圳市22.484467113.892684赤湾加油站-便利店购物;便利店
3深圳市南山区赤湾四路44号南山区深圳市22.484526113.890047海景商店购物;便利店
4深圳市南山区赤湾七路6南山区深圳市22.484872113.894957赤湾振兴商店购物;便利店
剩下就把信息存好就可以啦。平时清洗数据比这种复杂多了,不过真的很喜欢pandas



  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值