* 본 포스트는 개인연구/학습 기록 용도로 작성되고 있습니다.


[Python] 네이버API를 활용한 위치 정보 수집


네이버 클라우드 플랫폼 서비스 가입을 통해 주소별 위치 정보(위도, 경도)를 수집해올 수 있다.

단, 유료화 정책에 유의하자!

https://www.ncloud.com/product/applicationService/maps

map 서비스에 대해, 2019년 한정적으로 무료 이벤트를 추진중이다.

'무료 이용량 프로모션'은 2019년 1월 1일 부터 2019년 12월 31일까지 동일인(동일사업자)당 1개의 계정에 대해서만, API별 일정량을 무료로 제공합니다.

Q. 무료 이용량 프로모션은 언제까지 제공되나요?

A. 2019년 1월 1일 부터 2019년 12월 31일 까지 1년간 제공되며, 무료 이용량 초과 시 사용한 만큼 요금이 청구됩니다.

프로모션 기간이 끝나는 향후 2020년에 대한 프로모션 및 요금 정책에 대한 계획은 아직 정확히 정해진 것이 없습니다.

향후 계획에 대해 정해지면 수개월 전에 공지사항을 통해 안내드리도록 하겠습니다.



1. ID/Password 발급 받기


네이버클라우드 플랫폼에서 maps 서비스 이용을 위한 id/pw를 발급받고 아래와 같이 변수를 설정해 준다.

client_id = '발급받은 아이디'
client_secret = '발급받은 패스워드'



2. 함수 생성

import os
import sys
import urllib.request
import datetime
import time
import json
from config import *

def get_request_url(url):

    req = urllib.request.Request(url)
    req.add_header("X-NCP-APIGW-API-KEY-ID", client_id)
    req.add_header("X-NCP-APIGW-API-KEY", client_secret)
    try:
        response = urllib.request.urlopen(req)
        if response.getcode() == 200:
            print ("[%s] Url Request Success" % datetime.datetime.now())
            return response.read().decode('utf-8')
    except Exception as e:
        print(e)
        print("[%s] Error for URL : %s" % (datetime.datetime.now(), url))
        return None


def getGeoData(address):

    base = "https://naveropenapi.apigw.ntruss.com/map-geocode/v2/geocode"
    node = ""
    parameters = "?query=%s" % urllib.parse.quote(address)
    url = base + node + parameters

    retData = get_request_url(url)

    if (retData == None):
        print("결과 없음")
        return None
    else:
        return json.loads(retData)



3. 위치정보 수집


for x in range(1):
    req_addr = '서울특별시 종로구 세종로 81-3'
    print('\n\n')
    jsonResult = getGeoData(req_addr)

    if 'addresses' in jsonResult.keys():
        print('총 검색 결과: ', jsonResult['meta']['totalCount'])
        print('요청 주소: ', req_addr)

        item =  jsonResult['addresses'][x]
        print('---------------------------------------------------')
        print('주소: ', item['roadAddress'])
        print('위도: ', str(item['y']))
        print('경도: ', str(item['x']))
[2019-08-11 15:53:10.787024] Url Request Success
총 검색 결과:  1
요청 주소:  서울특별시 종로구 세종로 81-3
---------------------------------------------------
주소:  서울특별시 종로구 세종대로 175 세종이야기
위도:  37.5722440
경도:  126.9759352

결과로 얻게 되는 jsonResult에 포함된 내용을 살펴 보면 아래와 같다.

{'status': 'OK',
 'meta': {'totalCount': 1, 'page': 1, 'count': 1},
 'addresses': [{'roadAddress': '서울특별시 종로구 세종대로 175 세종이야기',
   'jibunAddress': '서울특별시 종로구 세종로 81-3 세종이야기',
   'englishAddress': '175, Sejong-daero, Jongno-gu, Seoul, Republic of Korea',
   'addressElements': [{'types': ['SIDO'],
     'longName': '서울특별시',
     'shortName': '서울특별시',
     'code': ''},
    {'types': ['SIGUGUN'], 'longName': '종로구', 'shortName': '종로구', 'code': ''},
    {'types': ['DONGMYUN'], 'longName': '세종로', 'shortName': '세종로', 'code': ''},
    {'types': ['RI'], 'longName': '', 'shortName': '', 'code': ''},
    {'types': ['ROAD_NAME'],
     'longName': '세종대로',
     'shortName': '세종대로',
     'code': ''},
    {'types': ['BUILDING_NUMBER'],
     'longName': '175',
     'shortName': '175',
     'code': ''},
    {'types': ['BUILDING_NAME'],
     'longName': '세종이야기',
     'shortName': '세종이야기',
     'code': ''},
    {'types': ['LAND_NUMBER'],
     'longName': '81-3',
     'shortName': '81-3',
     'code': ''},
    {'types': ['POSTAL_CODE'],
     'longName': '03172',
     'shortName': '03172',
     'code': ''}],
   'x': '126.9759352',
   'y': '37.5722440',
   'distance': 0.0}],
 'errorMessage': ''}

분리된 주소(시군구, 동면 등)에 대한 정보를 수집할 수도 있다.

print(item['roadAddress']) # 도로명 주소
print(item['jibunAddress']) # 지번 주소
print(item['y']) # 위도
print(item['x']) # 경도

for x in range(9):
    print(item['addressElements'][x]['types'][0], " : ", item['addressElements'][x]['longName'])
서울특별시 종로구 세종대로 175 세종이야기
서울특별시 종로구 세종로 81-3 세종이야기
37.5722440
126.9759352
SIDO  :  서울특별시
SIGUGUN  :  종로구
DONGMYUN  :  세종로
RI  :  
ROAD_NAME  :  세종대로
BUILDING_NUMBER  :  175
BUILDING_NAME  :  세종이야기
LAND_NUMBER  :  81-3
POSTAL_CODE  :  03172



5. 반복 실행 코드

많은 주소를 한꺼번에 처리할 때, 루프문을 통해 반복 Call한다.

1) 주소 목록 로드하기

target_list.to_csv("./datas/addresses.csv", index=False, encoding='euc-kr')

2) 주소 정보 수집 Call

loop_cnt = 0
success_cnt = 0
fail_cnt = 0

ROAD_ADDR = []
JIBUN_ADDR = []
SIDO = []
SIGUGUN = []
DONGMYUN = []
RI = []
ROAD_NAME = []
BUILDING_NUMBER = []
BUILDING_NAME = []
LAND_NUMBER = []
POSTAL_CODE = []
X = []
Y = []
success_addr = []
fail_addr = []

for x in range(len(target_list)):
    loop_cnt += 1
    req_addr = target_list.ADDR[x]

    try:
        jsonResult = getGeoData(req_addr)

        if jsonResult['meta']['totalCount'] > 0:
            item =  jsonResult['addresses'][0]
            success_addr.append(req_addr)

            ROAD_ADDR.append(item['roadAddress'])
            JIBUN_ADDR.append(item['jibunAddress'])
            SIDO.append(item['addressElements'][0]['longName'])
            SIGUGUN.append(item['addressElements'][1]['longName'])
            DONGMYUN.append(item['addressElements'][2]['longName'])
            RI.append(item['addressElements'][3]['longName'])
            ROAD_NAME.append(item['addressElements'][4]['longName'])
            BUILDING_NUMBER.append(item['addressElements'][5]['longName'])
            BUILDING_NAME.append(item['addressElements'][6]['longName'])
            LAND_NUMBER.append(item['addressElements'][7]['longName'])
            POSTAL_CODE.append(item['addressElements'][8]['longName'])
            X.append(item['x'])
            Y.append(item['y'])

            success_cnt += 1

        else:
            fail_cnt += 1
            fail_addr.append(req_addr)

    except:
        fail_cnt += 1
        fail_addr.append(req_addr)

3) 조회결과 건수 확인

loop_cnt, success_cnt, fail_cnt

4) 결과 파일 생성

실패한 목록 저장

now = datetime.datetime.now()
now_time = now.strftime('%Y-%m-%d %H:%M:%S')
times = []

if fail_cnt > 0:

    for x in range(fail_cnt):
        times.append(now_time)


    temp = pd.DataFrame()
    temp['ADDR'] = fail_addr
    temp['time'] = times


    fail_df = pd.merge(target_list, temp , how = 'right', on = 'ADDR')

    # 저장
    fail_df.to_csv("datas/fail_list.csv", mode = 'a', index=False, encoding = 'euc-kr')

성공한 목록 저장

now = datetime.datetime.now()
now_time = now.strftime('%Y-%m-%d %H:%M:%S')
times = []


if success_cnt > 0:

    for x in range(success_cnt):
        times.append(now_time)

    success_df = pd.DataFrame()

    success_df['ADDR'] = success_addr
    success_df['ROAD_ADDR'] = ROAD_ADDR
    success_df['JIBUN_ADDR'] = JIBUN_ADDR
    success_df['SIDO'] = SIDO
    success_df['SIGUGUN'] = SIGUGUN
    success_df['DONGMYUN'] = DONGMYUN
    success_df['RI'] = RI
    success_df['ROAD_NAME'] = ROAD_NAME
    success_df['BUILDING_NUMBER'] = BUILDING_NUMBER
    success_df['BUILDING_NAME'] = BUILDING_NAME
    success_df['LAND_NUMBER'] = LAND_NUMBER
    success_df['POSTAL_CODE'] = POSTAL_CODE
    success_df['X'] = X
    success_df['Y'] = Y
    success_df['time'] = times

    final_df = pd.merge(target_list, success_df , how = 'right', on = 'ADDR')

    # 저장
    final_df.to_csv("datas/final_list.csv", mode = 'a', index=False, encoding = 'euc-kr')

Tags:


Back to blog