Naver API로 길찾기(with python)

정예슬·2022년 2월 15일
5

API

목록 보기
1/2
post-thumbnail

Naver open API를 활용하여 경로를 탐색(길찾기)해 보려고 한다.
Naver API를 사용하기 위해서는 인증정보가 필요한데, 링크에서 원하는 API의 application을 등록하고 key를 등록받아 사용하면 된다.

어플리케이션 등록이 완료되면 다음과 같이 인증 번호가 발급된다. API마다 무료 사용 한도가 있으므로 개별적으로 사용해야 한다. 서비스 url을 지정하라는데 나는 개인 프로젝트 용으로 사용해서 대충 아무 링크나 넣었다.

본 프로젝트에서 사용하고자 하는 api는 geocoding, directions 5 두 가지인데, 본 api에 대한 상세한 개요 및 설명은 링크에서 확인할 수 있다.

🌍 Geocoding 개요


Geocoding은 주소를 지도상의 좌표로 변환하는 방법이다.
예를 들어 서울특별시 종로구 청와대로 1 라는 주소를 입력했을 때, geocoding을 거치면 '37.5862701', '126.9766002'라는 위도 경도 좌표로 환산된다.

본 프로젝트에서 geocoding이 필요한 이유는, directions 5가 request parameters로 좌표를 요구하기 때문이다. 즉 주소를 입력받아 geocoding으로 한 번 변환을 거쳐, directions 5로 경로를 도출하는 과정이 필요하다.

# *-- Geocoding 활용 코드 --*
import json
import urllib
from urllib.request import Request, urlopen
# *-- 3개의 주소 geocoding으로 변환한다.(출발지, 도착지, 경유지) --*
start = '서울특별시 종로구 청와대로 1'
goal = '부산광역시 금정구 부산대학로63번길 2'
waypoint = '경기도 수원시 장안구 서부로 2149'

# 주소에 geocoding 적용하는 함수를 작성.
def get_location(loc) :
    client_id = '-- 발급받은 client id 입력 --'
    client_secret = '-- 발급받은 client secret 입력 --'
    url = f"https://naveropenapi.apigw.ntruss.com/map-geocode/v2/geocode?query=" \
    			+ urllib.parse.quote(loc)
    
    # 주소 변환
    request = urllib.request.Request(url)
    request.add_header('X-NCP-APIGW-API-KEY-ID', client_id)
    request.add_header('X-NCP-APIGW-API-KEY', client_secret)
    
    response = urlopen(request)
    res = response.getcode()
    
    if (res == 200) : # 응답이 정상적으로 완료되면 200을 return한다
        response_body = response.read().decode('utf-8')
        response_body = json.loads(response_body)
        print(response_body)
        # 주소가 존재할 경우 total count == 1이 반환됨.
        if response_body['meta']['totalCount'] == 1 : 
        	# 위도, 경도 좌표를 받아와서 return해 줌.
            lat = response_body['addresses'][0]['y']
            lon = response_body['addresses'][0]['x']
            return (lon, lat)
        else :
            print('location not exist')
        
    else :
        print('ERROR')
        
#  함수 적용
start = get_location(start)
goal = get_location(goal)
waypoint = get_location(waypoint)

directions 5는 출발지(start), 도착지(goal), 경유지(waypoint)를 지정하여 경로를 탐색할 수 있기 때문에, 세 가지 주소를 입력하여 geocode를 적용해보았다.

🌏 Directions 5 개요


Geocoding된 3개의 좌표를 가지고 경로를 탐색해 본다. 여기서 출발지, 목적지는 필수 사항이지만 경유지는 optional한 parameter이다.(없어도 무방)

# *-- Directions 5 활용 코드 --*
option = ''
# option : 탐색옵션 [최대 3개, traoptimal(기본 옵션) 
# / trafast, tracomfort, traavoidtoll, traavoidcaronly]

def get_optimal_route(start, goal, waypoints=waypoint, option=option ) :
    # waypoint는 최대 5개까지 입력 가능, 
    # 구분자로 |(pipe char) 사용하면 됨(x,y 좌표값으로 넣을 것)
    # waypoint 옵션을 다수 사용할 경우, 아래 함수 포맷을 바꿔서 사용 
    client_id = '-- 발급받은 client id 입력 --'
    client_secret = '-- 발급받은 client secret 입력 --' 
    # start=/goal=/(waypoint=)/(option=) 순으로 request parameter 지정
    url = f"https://naveropenapi.apigw.ntruss.com/map-direction-15/v1/driving? \
    start={start[0]},{start[1]}&goal={goal[0]},{goal[1]}\
    &waypoints={waypoint[0]},{waypoint[1]}&option={option}"
    request = urllib.request.Request(url)
    request.add_header('X-NCP-APIGW-API-KEY-ID', client_id)
    request.add_header('X-NCP-APIGW-API-KEY', client_secret)
    
    response = urllib.request.urlopen(request)
    res = response.getcode()
    
    if (res == 200) :
        response_body = response.read().decode('utf-8')
        return json.loads(response_body)
            
    else :
        print('ERROR')
        
get_optimal_route(start, goal, option=option)

코드를 입력하면 상당히 많은 정보들이 나오게 된다.
정상적으로 경로 탐색에 성공했다면, '길찾기에 성공했습니다' 라는 메시지를 띄우고, route에 검색옵션으로 탐색된 경로의 총 거리, 총 소요시간, 총 요금(유류비,톨비 등) 등이 담겨있다. section에서는 경로의 주요 도로 정보가, guide 에서는 목적지까지의 guidence가 제공된다.

# *-- 목적지까지의 종합 정보 추출(총 거리, 총 소요시간, 요금 등) --*
message = {
    'message' : results['message'], # traoptimal은 option 에 따라 다르게 줄 것
    'option' : list(results['route'].keys())[0],
    'total_distance' : results['route']['traoptimal'][0]['summary']['distance'],
    'total_duration' : results['route']['traoptimal'][0]['summary']['duration'],
    'fares' : {'toll' : results['route']['traoptimal'][0]['summary']['tollFare'],
              'taxi' : results['route']['traoptimal'][0]['summary']['taxiFare'],
              'fuel' : results['route']['traoptimal'][0]['summary']['fuelPrice']}
}
print(message)

# *-- 목적지까지의 guidence와 각각의 거리, 소요시간 정보 추출 --*
temp = [ (guide['instructions'], guide['distance'] , guide['duration'] / 1000 ) \
for guide in results['route']['traoptimal'][0]['guide'] ]

print(temp)

원하는 정보만 추출하고 싶을 때 message, temp 코드를 사용하면 된다.

profile
춘식이랑 함께하는 개발일지

1개의 댓글

comment-user-thumbnail
2022년 7월 28일

안녕하세요 좋은 글 게시해주셔서 감사합니다 .

여쭈어볼게 있는데요
제가 start=[126.977677,37.584723]
goal=[127.004126,37.560909]
로 지정해두고
올려주신 코드를 돌렸는데
start={start[0]},{start[1]}&goal={goal[0]},{goal[1]}"
^
SyntaxError: cannot assign to set display
이라는 오류가 나와 여기서 애를 먹고 있습니다.

혹시 원인이랑 해결방안을 알 수 있을까요?
댓글로 알려주셔도 되고 가능하시면 메일로 연락해주시길 부탁드립니다. 사례도 해드리고 싶네요.
soomin9636@naver.com 입니다..
아래는 적용한 코드입니다.

-- Directions 5 활용 코드 --

option = ''

option : 탐색옵션 [최대 3개, traoptimal(기본 옵션)

/ trafast, tracomfort, traavoidtoll, traavoidcaronly]

def get_optimal_route(start, goal, waypoints=['',''], option=option ) :
client_id = '-------------'
client_secret = '------------------------------------------'

# start=/goal=/(waypoint=)/(option=) 순으로 request parameter 지정
url = f"https://naveropenapi.apigw.ntruss.com/map-direction-15/v1/driving?
start={start[0]},{start[1]}&goal={goal[0]},{goal[1]}"
request = urllib.request.Request(url)
request.add_header('X-NCP-APIGW-API-KEY-ID', client_id)
request.add_header('X-NCP-APIGW-API-KEY', client_secret)

response = urllib.request.urlopen(request)
res = response.getcode()

if (res == 200) :
    response_body = response.read().decode('utf-8')
    return json.loads(response_body)
        
else :
    print('ERROR')
    

get_optimal_route(start, goal, option=option)

답글 달기