Python中使用GoogleMaps API(包含Geocoding API,Places API Web Service )详细教程

来源:互联网 发布:删除root软件 编辑:程序博客网 时间:2024/05/19 06:39

前言

业务需要根据经纬度获取该城市的邮政编码,需要通过调用GoogleMaps来搜索地点,来获取地点的详细信息。于是查阅了一些相关的资料,特意分享出来给大家参考参考。
涉及相关的资料:
google官方文档
GoogleMaps Geocoding API:https://developers.google.com/maps/documentation/geocoding/geocoding-strategies
GoogleMaps Places API Web Service:https://developers.google.com/places/web-service/search?hl=zh-tw

使用的python包:
http://github.com/slimkrazy/python-google-places
https://github.com/googlemaps/google-maps-services-python

前提条件:你能够正常访问Google!

如果不能正常访问到google就想用GoogleMaps,那这就比较尴尬了,我也很无奈。

1.准备工作

你得有个google账号,打开https://console.developers.google.com/apis/credentials?project=imperial-palace-174906&authuser=0

1.1创建google项目获取项目秘钥

如果还没创建项目的话,那先创建个项目,我这里是创建了一个googlemaps的项目
googlemaps项目及其秘钥
请记住3中圈中的秘钥,我们代码中要使用到。

1.2在项目中添加googleMaps服务:Google Maps Geocoding API,Google Places API Web Service

在刚刚创建的项目库中,添加googleMaps的Google Maps Geocoding API和Google Places API Web Service
项目库中添加googlemap服务
(由于我已经添加了,所以列表中是没有显示的)

1.3然后在信息中心就可以看到你刚才添加的两个maps服务

信息中心
上面的图片是最近是用项目秘钥请求这个maps服务的一些图标

2.安装python所需的包(我使用的是python2.7.12版本)

两个包分别是:
http://github.com/slimkrazy/python-google-places (警示:这个包存在一个严重的bug,详情:http://blog.csdn.net/dongyouyuan/article/details/77169560)
pip安装:pip install python-google-places
https://github.com/googlemaps/google-maps-services-python
pip安装:pip install -U googlemaps
你会发现googlemaps中也有python-google-places中的功能,想问我为毛还用一个第三方的包,然而我真的无言以对,鬼知道我当初为什么用这个包。0.0(我当时搜google maps places api python 第一个就是 http://github.com/slimkrazy/python-google-places就用了)后面看有没有时间,对比一下这包和google官方包的区别
————-2017-08-04补充———————————————————————————————————–
看了一下googlemaps中的python-google-places的功能,发现其返回地点的内容实在是少,只有寥寥无几的几个字段。 http://github.com/slimkrazy/python-google-places中详细程度真的是很厉害。所用用它是没错的

{            "rating": 5,             "name": "STR Analytics",             "reference": "CmRRAAAAEyrq32Ve7RKLtI6CWpaAoTFrR2yVWlKTfnbNTmCRLj3yXcIs2k6H45JPPwPZyIpMPxEBfVIqdD9BTWekJliAvgX_OH-FJyYUWnso9oZ2CjN97I2GWhXTSK1TBUo3HBVxEhDRxa-R4nxh8UqHeJPi9LHtGhQ6VMxxTnuXCwm9vZgY0IcnTaqQhg",             "geometry": {                "location": {                    "lat": 39.9148173,                     "lng": -105.1206877                },                 "viewport": {                    "northeast": {                        "lat": 39.9158015802915,                         "lng": -105.1193284197085                    },                     "southwest": {                        "lat": 39.9131036197085,                         "lng": -105.1220263802915                    }                }            },             "place_id": "ChIJ1VlFO-Tta4cRGQHpjODHvXU",             "formatted_address": "11001 W 120th Ave, Broomfield, CO 80021, United States",             "id": "b0003b168c40b2d378933f440b7f9a4116187dc5",             "types": [                "point_of_interest",                 "establishment"            ],             "icon": "https://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png"        },

—————2017-08-04补充完毕————————————————————————————————————

3.简单粗暴的代码

#!/usr/bin/env python# -*- coding: utf-8 -*-# @Author: Dongyouyuan# @Software: PyCharm# @File: googleMap.py# @Time: 17-8-2 上午11:31from googleplaces import GooglePlacesimport googlemapsimport sysreload(sys)sys.setdefaultencoding('utf8')class GoogleMaps(object):    """提供google maps服务"""    def __init__(self):        self._GOOGLE_MAPS_KEY = "你的秘钥"        self._Google_Places = GooglePlaces(self._GOOGLE_MAPS_KEY)        self._Google_Geocod = googlemaps.Client(key=self._GOOGLE_MAPS_KEY)    def _text_search(self, query, language=None, location=None):        """        根据搜索字符串,请求google API传回推荐的列表        :param query: 搜索字符串        :param language: 语言        :param location: 地区筛选        :return:        """        # lat_lng = {"lat": "22.5745761", "lng": "113.9393772"}        # 经纬度附近搜索        # text_query_result = self.self._Google_Places.text_search(query='Gong Yuan', lat_lng=lat_lng)        # location 为人可认识的名称        # text_query_result = self.self._Google_Places.text_search(query='Tang Lang Shan', location='shenzhen')        # 指定语言搜索        text_query_result = self._Google_Places.text_search(query=query, language=language, location=location)        return text_query_result.places    def _reverse_geocode(self, lat, lng, language=None):        """        根据经纬度请求google API获取坐标信息,返回信息        :param lat: 纬度        :param lng:经度        :param language:语言        :return:        """        # 根据经纬度获取地址信息 pincode        list_reverse_geocode_result = self._Google_Geocod.reverse_geocode((lat, lng), language=language)        # print json.dumps(list_reverse_geocode_result, indent=4)        return list_reverse_geocode_result    def _return_reverse_geocode_info(self, lat, lng, language=None):        """        整理信息        :param lat:纬度        :param lng:经度        :param language:语言        :return:        """        list_reverse_geocode = self._reverse_geocode(lat, lng, language=language)        if list_reverse_geocode:            city = ''            pincode = ''            route = ''            neighborhood = ''            sublocality = ''            administrative_area_level_1 = ''            country = ''            street_number = ''            # 全名地址            formatted_address = list_reverse_geocode[0]['formatted_address']            for address_info in list_reverse_geocode[0]['address_components']:                # 城市标识为locality                if 'locality' in address_info['types']:                    city = address_info['long_name']                # 邮政编码标识为postal_code                elif 'postal_code' in address_info['types']:                    pincode = address_info['long_name']                # 街道路                elif 'route' in address_info['types']:                    route = address_info['long_name']                # 相似地址名                elif 'neighborhood' in address_info['types']:                    neighborhood = address_info['long_name']                # 地区名                elif 'sublocality' in address_info['types']:                    sublocality = address_info['long_name']                # 省份                elif 'administrative_area_level_1' in address_info['types']:                    administrative_area_level_1 = address_info['long_name']                # 国家                elif 'country' in address_info['types']:                    country = address_info['long_name']                # 门牌号                elif 'street_number' in address_info['types']:                    street_number = address_info['long_name']            return {'city': city, 'pincode': pincode, 'route': route, 'neighborhood': neighborhood,                    'sublocality': sublocality, 'administrative_area_level_1': administrative_area_level_1,                    'country': country, 'formatted_address': formatted_address, 'street_number': street_number}        else:            return None    def get_pincode_city(self, lat, lng, language=None):        """        根据经纬度获取该地区详细信息        :param lat: 纬度        :param lng: 经度        :return:        """        reverse_geocode_info = self._return_reverse_geocode_info(lat, lng, language=language)        if reverse_geocode_info:            return {'city': reverse_geocode_info['city'], 'pincode': reverse_geocode_info['pincode']}        else:            return None    def get_address_recommendation(self, query, language=None, location=None):        """        获取输入地址的推荐地址(最多返回5个)        :param query: 搜索地址名称        :param language: 语言        :param location: 地区筛选        :return:        """        return_size = 5        list_return_info = list()        list_places_text_search_result = self._text_search(query=query, language=language, location=location)        # 默认返回5条数据        if len(list_places_text_search_result) > return_size:            list_places_text_search_result = list_places_text_search_result[:return_size]        for place in list_places_text_search_result:            result_geocode = self._return_reverse_geocode_info(place.geo_location['lat'], place.geo_location['lng'], language=language)            # 数据不为空            if result_geocode:                # 地点全路径加上地点名                result_geocode['formatted_address'] = '{} {}'.format(place.name, result_geocode['formatted_address'])                result_geocode['place_name'] = place.name                # 经纬度                result_geocode['lat'] = '{}'.format(place.geo_location['lat'])                result_geocode['lng'] = '{}'.format(place.geo_location['lng'])                list_return_info.append(result_geocode)        return list_return_infoif __name__ == '__main__':    # 使用实例    import json    google_maps = GoogleMaps()    result_recommendation_list = google_maps.get_address_recommendation(query='天河公园', language='zh', location='中国')    pincode_city = google_maps.get_pincode_city(22.547143, 114.062753)    print json.dumps(result_recommendation_list, indent=4, encoding='utf-8')    print '*'*100    print pincode_city

4.输出结果

{    "code": 0,    "data": {        "address_recommendation": [            {                "administrative_area_level_1": "广东省",                "city": "广州市",                "country": "中国",                "formatted_address": "天河公园 中国广东省广州市天河区天河公园华翠街66号",                "lat": "23.1267447",                "lng": "113.3679628",                "neighborhood": "天河公园",                "pincode": "",                "place_name": "天河公园",                "route": "华翠街",                "street_number": "66",                "sublocality": "天河区"            },            {                "administrative_area_level_1": "广东省",                "city": "广州市",                "country": "中国",                "formatted_address": "天河公园(东门) 中国广东省广州市天河区天河公园华翠街66号",                "lat": "23.12583799999999",                "lng": "113.368506",                "neighborhood": "天河公园",                "pincode": "",                "place_name": "天河公园(东门)",                "route": "华翠街",                "street_number": "66",                "sublocality": "天河区"            },            {                "administrative_area_level_1": "广东省",                "city": "广州市",                "country": "中国",                "formatted_address": "天河公园(西门) 中国广东省广州市天河区天河公园天府路139号",                "lat": "23.128752",                "lng": "113.363186",                "neighborhood": "天河公园",                "pincode": "",                "place_name": "天河公园(西门)",                "route": "天府路",                "street_number": "139",                "sublocality": "天河区"            },            {                "administrative_area_level_1": "广东省",                "city": "广州市",                "country": "中国",                "formatted_address": "天河公园(南1门) 中国广东省广州市天河区天河公园黄埔大道中199号",                "lat": "23.12312",                "lng": "113.365254",                "neighborhood": "天河公园",                "pincode": "",                "place_name": "天河公园(南1门)",                "route": "黄埔大道中",                "street_number": "199",                "sublocality": "天河区"            },            {                "administrative_area_level_1": "广东省",                "city": "广州市",                "country": "中国",                "formatted_address": "天河公园(北1门) 中国广东省广州市天河区天河公园中山大道西246号-540号 邮政编码: 510640",                "lat": "23.131274",                "lng": "113.367319",                "neighborhood": "天河公园",                "pincode": "510640",                "place_name": "天河公园(北1门)",                "route": "中山大道西",                "street_number": "246号-540号",                "sublocality": "天河区"            }        ]    },    "msg": "ok"}****************************************************************************************************{'city': u'Shenzhen Shi', 'pincode': u'518000'}

5.代码解析

以上代码已经有很清晰的注释了,但是我还是要简单明了的说一下吧。

GoogleMaps类提供两个对外服务的方法:
get_address_recommendation:根据用户的搜索字符和地区过滤,获得最多5条的返回结果,值得一提的是该函数的参数language是控制返回结果的语言,也就是说,你可以搜query是park,location=’America’,language=’zh’,
get_pincode_city:根据经纬度获取该地区的邮政编码和城市名称(我做了截取,只截取了城市和邮政编码,事实上可以获取该地区的所有详细信息,你可以打印get_pincode_city方法里面的reverse_geocode_info变量,你会有惊喜的发现)

总结

当然我只是根据业务要求做了一个特定的定制化,当然GoogleMaps是不止我用得那么简单的,其中还有更多有趣,高级的功能,希望有兴趣的同学可以继续深研下去。希望这篇文章能帮到大家,感谢各位!