본문으로 바로가기

Google Map API

category python 프로젝트(google map api) 2020. 5. 27. 04:33

 

웹 API

 

API는 웹 애플리케이션 개발에서 다른 서비스에 요청을 보내고 응답을 받기 위해 정의된 것이다.

 

예를 들어 블로그 API를 이용하면 블로그에 접속하지 않고도 다른 방법으로 글을 올릴 수 있다.

 

그 외에 우체국의 우편번호 API, 구글과 네이버의 지도 API등 유용한 API들이 많으므로, 요즘은 홈페이지 구축이나 추가개편 시 따로 추가로 개발하지 않고 이런 오픈 API를 가져와 사용하는 추세다.

 


 

Google Map API

 

 

#1 환경 구축하기

구글 map api 제공 사이트:https://cloud.google.com/maps-platform

 

Geolocation API  |  Google Maps Platform  |  Google Cloud

Google Maps Platform을 선택하면 정확한 실시간 데이터 및 동적 이미지로 몰입형 위치정보 활용 환경을 만들고 더 나은 비즈니스 의사결정을 내릴 수 있습니다.

cloud.google.com

 

 

1. 시작하기

 

2. 원하는 제품 선택

 

3. 프로젝트 이름 설정

4.결제 방법 설정   (실제로 결제 안됨으로 걱정 안해도)

 

 

5. 사용할 수 있는 인증키 발급

 

 

6. 명령 프롬프트에서 google maps 다운

 

 

(1)pip install googlemaps

 

 

     +  pip:간단하게 말하면 라이브러리들의 설치를 아주아주 편하고 쉽게 도와주는 프로그램.

 

 

 

(2)pip install folium

 

 

+folium위치정보를 시각화하기 위한 라이브러리다

 

 

#2 파이썬으로 활용하기

 

 

원하는 장소의 정보 불러오기

import googlemaps


gmaps =googlemaps.Client(key=gmaps_key(부여받은 개인키))
geo=gmaps.geocode('대한민국 서울특별시 강남구 대치2동 514')
print(geo)

 

결과값

 

 

결과값을 보면 정리가 안된 json 파일형태로 출력된다.

 

 

아래는 보기편하게 정리된 json 형태로 정리한 것이다.

[{
	'access_points': [],
	'address_components': [{
		'long_name': '514',
		'short_name': '514',
		'types': ['premise']
	}, {
		'long_name': '대치2동',
		'short_name': '대치2동',
		'types': ['political', 'sublocality', 'sublocality_level_2']
	}, {
		'long_name': '강남구',
		'short_name': '강남구',
		'types': ['political', 'sublocality', 'sublocality_level_1']
	}, {
		'long_name': '서울특별시',
		'short_name': '서울특별시',
		'types': ['administrative_area_level_1', 'political']
	}, {
		'long_name': '대한민국',
		'short_name': 'KR',
		'types': ['country', 'political']
	}, {
		'long_name': '135-282',
		'short_name': '135-282',
		'types': ['postal_code']
	}],
	'formatted_address': '대한민국 서울특별시 강남구 대치2동 514',
	'geometry': {
		'location': {
			'lat': 37.495846,
			'lng': 127.0722393
		},
		'location_type': 'ROOFTOP',
		'viewport': {
			'northeast': {
				'lat': 37.4971949802915,
				'lng': 127.0735882802915
			},
			'southwest': {
				'lat': 37.4944970197085,
				'lng': 127.0708903197085
			}
		}
	},
	'place_id': 'ChIJpS4nCDCkfDURrKqALLHBeXo',
	'plus_code': {
		'compound_code': 'F3WC+8V 대한민국 서울특별시',
		'global_code': '8Q99F3WC+8V'
	},
	'types': ['street_address']
}]

 

주소를 분리해서 출력하기

#주소 분리

from urllib.parse import quote
from urllib.request import Request, urlopen
import ssl
import json

kor_url = quote('대한민국 서울특별시 강남구 대치2동 514')
url = 'https://maps.googleapis.com/maps/api/geocode/json?address='+ kor_url +
'&key=''부여받은 개인키''&language=ko'

req = Request(url, headers={ 'X-Mashape-Key': 'key(부여받은 개인키)' })
ssltext = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
company_addr_json = urlopen(req, context=ssltext).read().decode('utf8')

addr = json.loads(company_addr_json)

addr_detail = addr['results'][0]
#전체 주소
full_addr = addr_detail['formatted_address']
#시도 주소
city_addr1 = addr_detail['address_components'][4]['long_name']
#구 주소
city_addr = addr_detail['address_components'][3]['long_name']
#동,읍 주소
go_addr = addr_detail['address_components'][2]['long_name']
#대로 주소
dong_addr = addr_detail['address_components'][1]['long_name']
#번지 주소
bunji_addr = addr_detail['address_components'][0]['long_name']
print(addr_detail)
print(full_addr)
print(city_addr1)
print(city_addr)
print(go_addr)
print(dong_addr)
print(bunji_addr)

json의 배열인덱스들을 지정해줘서 원하는 값들을 뽑아낸다

 

 

 

좌표로 지도 저장

#좌표로 지도 저장

import folium
map_osm = folium.Map(location=[37.566345, 126.977893],zoom_start=17)

map_osm.save('C:\제혁\지도 사진들/map2.html')

 

 

 

좌표에 마크 지정

#좌표에 마크 지정

import folium
map_osm = folium.Map(location=[37.566345, 126.977893],zoom_start=17)

folium.Marker([37.566345, 126.977893], popup='서울특별시청').add_to(map_osm)

map_osm.save('C:\제혁\지도 사진들/map1.html')

 

 

 

 

 

좌표 사이 거리 구하기

#좌표 사이 거리 구하기

import numbers
import math

class GeoUtil:
    """
    Geographical Utils
    """
    @staticmethod
    def degree2radius(degree):
        return degree * (math.pi/180)
    
    @staticmethod
    def get_harversion_distance(x1, y1, x2, y2, round_decimal_digits=5):
        """
        경위도 (x1,y1)과 (x2,y2) 점의 거리를 반환
        Harversion Formula 이용하여 2개의 경위도간 거래를 구함(단위:Km)
        """
        if x1 is None or y1 is None or x2 is None or y2 is None:
            return None
        assert isinstance(x1, numbers.Number) and -180 <= x1 and x1 <= 180
        assert isinstance(y1, numbers.Number) and  -90 <= y1 and y1 <=  90
        assert isinstance(x2, numbers.Number) and -180 <= x2 and x2 <= 180
        assert isinstance(y2, numbers.Number) and  -90 <= y2 and y2 <=  90

        R = 6371 # 지구의 반경(단위: km)
        dLon = GeoUtil.degree2radius(x2-x1)    
        dLat = GeoUtil.degree2radius(y2-y1)

        a = math.sin(dLat/2) * math.sin(dLat/2) \
            + (math.cos(GeoUtil.degree2radius(y1)) \
              *math.cos(GeoUtil.degree2radius(y2)) \
              *math.sin(dLon/2) * math.sin(dLon/2))
        b = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
        return round(R * b, round_decimal_digits)

    @staticmethod
    def get_euclidean_distance(x1, y1, x2, y2, round_decimal_digits=5):        
        """
        유클리안 Formula 이용하여 (x1,y1)과 (x2,y2) 점의 거리를 반환
        """
        if x1 is None or y1 is None or x2 is None or y2 is None:
            return None
        assert isinstance(x1, numbers.Number) and -180 <= x1 and x1 <= 180
        assert isinstance(y1, numbers.Number) and  -90 <= y1 and y1 <=  90
        assert isinstance(x2, numbers.Number) and -180 <= x2 and x2 <= 180
        assert isinstance(y2, numbers.Number) and  -90 <= y2 and y2 <=  90

        dLon = abs(x2-x1) # 경도 차이
        if dLon >= 180:   # 반대편으로 갈 수 있는 경우
            dLon -= 360   # 반대편 각을 구한다
        dLat = y2-y1      # 위도 차이
        return round(math.sqrt(pow(dLon,2)+pow(dLat,2)),round_decimal_digits)

# 서울시청 126.97843, 37.56668
# 강남역   127.02758, 37.49794


print(GeoUtil.get_euclidean_distance(126.97843, 37.56668, 127.02758, 37.49794))

 

 

결과값:0.0845

 

받아오는 값의 주소 원리

 

주소의 기본 틀

https://maps.googleapis.com/maps/api/directions/json?origin&destination&mode&departure_time&key

 

 

 

  • origin = 위도, 경도

설명 : 출발지

 

예시 : origin=41.43206,-81.38992

주의할점 : 위도와 경도 사이에 공백 없어야함 문자열 형식으로 묶지말고 숫자로 바로 쓸 것

 

  • destination = 위도, 경도

설명 : 도착지

 

예시 : destination=41.43206,-81.38992

주의할 점 : 위도와 경도 사이에 공백 없어야함, 문자열 형식으로 묶지말고 숫자로 바로 쓸 것

 

  • mode = driving, walking, bicycling, transit

설명 : 길찾기 모드를 선택한다. 기본값은 driving 이며, 각각 도보, 자전거, 대중교통을 나타낸다.

 

  • departure_time = 초단위정수

설명 : 출발 시간을 설정 할 수 있다

 

예시 departure_time=1343641500 일 경우 2012  7  30 일 오전 9:45에 출발 하도록 설정한 값인데, 이는 UTC 1970  1 1 0 0 0초 부터 경과한 초를 정수로 반환한 값을 사용한다. 만약 지금 시간으로 설정하고 싶을경우 departure_time=now로 입력하면 된다.

 

적용된 주소

https://maps.googleapis.com/maps/api/directions/json?origin=37.5728359,126.9746922&destination=37.5129907,127.1005382&mode=transit&departure_time=now&key=API Key

 

 

중요!!! 걸리는 시간 초로 나타내기

 

 

설정한 주소값들을 적용

#중요!!! 걸리는 시간 초로 나타내기

# coding: utf-8
import time
import json
import os
import ssl
import urllib.request


if (__name__ == "__main__") :



    origin          = "37.5728359,126.9746922"
    destination     = "37.5129907,127.1005382"
    mode            = "transit"
    departure_time  = "now"
    key             = 'key(부여받은 개인키)'

    url = "https://maps.googleapis.com/maps/api/directions/json?origin="+ origin \
            + "&destination=" + destination \
            + "&mode=" + mode \
            + "&departure_time=" + departure_time\
            + "&language=ko" \
            + "&key=" + key

    request         = urllib.request.Request(url)
    context         = ssl._create_unverified_context()
    response        = urllib.request.urlopen(request, context=context)
    responseText    = response.read().decode('utf-8')
    responseJson    = json.loads(responseText)

    with open("./Agent_Transit_Directions.json","w") as rltStream :
        json.dump(responseJson,rltStream)



if ( __name__ == "__main__" ) :

    wholeDict = None
    with open("./Agent_Transit_Directions.json","r") as transitJson :
        wholeDict = dict(json.load(transitJson))

    path            = wholeDict["routes"][0]["legs"][0]
    duration_sec    = path["duration"]["value"]
    start_geo       = path["start_location"]
    end_geo         = path["end_location"]

    print(duration_sec) #전체 걸리는 시간을 초로 나타낸 것
    print(start_geo)	#출발지 위도,경도
    print(end_geo)	#도착지 위도,경도

결과값

//걸리는 초
3394 
//출발하는 위도와 경도
{'lat': 37.5728359, 'lng': 126.9746922} 
//도착하는 위도와 경도
{'lat': 37.5129907, 'lng': 127.1005382}

 

 

위도 경도 추출

##위도 경도 추출

import requests

# 검색할 주소
location = '강남 할리스'

# 요청 주소(구글맵)

# Local(테스트) 환경 - https 요청이 필요없고, API Key가 따로 필요하지 않지만 횟수에 제약이 있습니다.
URL = 'http://maps.googleapis.com/maps/api/geocode/json?sensor=false&language=ko&address={}' \
.format(location)

# Production(실제 서비스) 환경 - https 요청이 필수이고, API Key 발급(사용설정) 및 과금 설정이 반드시 필요합니다.
URL = 'https://maps.googleapis.com/maps/api/geocode/json?key=key(부여받은 개인키)' \
'&sensor=false&language=ko&address={}'.format(location)

# URL로 보낸 Requst의 Response를 response 변수에 할당
response = requests.get(URL)

# JSON 파싱
data = response.json()

# lat, lon 추출
lat = data['results'][0]['geometry']['location']['lat']
lng = data['results'][0]['geometry']['location']['lng']

# print() 함수 대신 pprint.pprint() 함수를 사용하는 이유는 좀 더 보기 쉽게 출력하기 위함입니다.
print(lat)
print(lng)

 

//위도
37.49873340000001 
//경도
127.0278077