주소로 위도,경도 값 가져오기

peace w·2024년 9월 25일
1

지오코딩(Geocoding)

  • 주소를 위/경도 정보로 변환하는 것

Geopy 사용하기

  • 프로젝트를 위해 네이버 지도를 크롤링해서 음식점 데이터를 모았다. 지도에 음식점들을 표시하기 위해선 위도/경도 값이 필요했다.
  • 파이썬으로 Geopy 라이브러리를 사용하면 다른 api를 쓰지 않고 간단하게 지오코딩을 할 수 있다.
  • Geopy는 무료 오픈소스인 openStreetMap을 사용하고 있다.
import geopy

geolocoder = Nominatim(user_agent = 'South Korea')

def geocoding(address): 
    geo = geolocoder.geocode(address)
    crd = (geo.latitude, geo.longitude)
    print(crd)
    return crd
  • 쉽다는 장점이 있으나 이 경우 단순히 도로명주소를 토대로 좌표값을 가져오는 것이므로, 큰 건물안에 입점한 작은 음식점의 정확한 위치가 필요한 경우에는 적절하지 않다.

  • 하이디라오 코엑스 점을 검색해보면 주소가 서울 강남구 테헤란로87길 58 지하2층으로 나온다.
  • 이 주소값을 좌표로 변환하려면 지하2층(몇 층, 몇 호 같은 정보)은 불필요하며, 변환 시 오류가 생길 수 있다.
  • 그래서 서울 강남구 테헤란로 87길 58의 위경도 좌표를 가져오게 되면

  • 하이디라오 뿐만 아니라, 서울 강남구 테헤란로 87길 58에 해당하는 주소를 가지는 가게들이 매우 많다. 그럼 이 가게들은 전부 같은 좌표를 갖게되는 것이다.

네이버 검색 api 사용하기

https://developers.naver.com/docs/serviceapi/search/local/local.md#%EC%A7%80%EC%97%AD

  • 각 가게들의 정확한 좌표를 찾기 위해 네이버 검색 api를 사용했다.

  • 카카오 api도 있으나, 네이버와 카카오에 등록된 업체명이 다른 경우가 있기 때문에 네이버 지도를 통해서 크롤링했으니 네이버를 사용하는 게 낫다고 생각했다.

  • Application > 애플리케이션 등록 : 우선 api를 사용신청해준다.

  • 로컬에서 사용하기 위해 url을 로컬호스트로 설정했다.

https://openapi.naver.com/v1/search/local.json?query={여기에 검색할 이름}&display=5&start=1&sort=random

이 URL을 통해서 검색 API를 요청할 수 있다.

  • display : 한 번에 표시할 검색 개수(최대 5개로 제한)
  • start : 검색 시작 위치
  • sort : 검색 결과 정렬 방법. random은 정확도순으로 내림차순 정렬하며 기본값이다. comment는 업체 및 기관에 대한 카페, 블로그의 리뷰 개수순으로 내림차순 정렬한다.
    • 기본값으로 계속 진행했으나...가게 이름 풀네임을 검색해도 제대로 안 뜨는 경우가 있었기 때문에 정확도순 기준이 어떤지는 잘 모르겠다.

  • 우선 포스트맨으로 api가 잘 작동하는지 테스트 할 것이다.

    X-Naver-Client-Id: {애플리케이션 등록 시 발급받은 클라이언트 아이디 값}
    X-Naver-Client-Secret: {애플리케이션 등록 시 발급받은 클라이언트 시크릿 값}
    을 헤더로 넣어줘야한다.

  • "하이디라오 코엑스점"으로 검색했고, 이런 결과가 나온다.
    여기서 mapx, mapy값을 가져와서 127.0575397, 37.5120151이 위/경도 값이 된다.

  • 작성한 코드는 아래와 같다.
import pandas as pd
import requests
import json


df = pd.read_csv('음식점 정보.csv')

mapx_list = []
mapy_list = []

# csv 파일의 name 컬럼의 값들을 돌면서 검색 api 실행
for name in df['name']:
  url =  f"https://openapi.naver.com/v1/search/local.json?query={name}&display=5&start=1&sort=random"
  headers = {
    'X-Naver-Client-Id': CLIENT_ID,
    'X-Naver-Client-Secret': CLIENT_SECRET
  }
  response = requests.get(url, headers=headers)

  if response.status_code == 200:
    result = response.json()
    print(result)  # API 응답을 출력하여 확인
  • 상태 코드가 200인 경우에 계속 진행하면서, api 응답을 출력하여 확인할 수 있게 했다.
		# items 의 결과가 있으면
          if len(result['items']) > 0:
            found = False
            for item in result['items']:
              if 'roadAddress' in item:
                road_address_parts = item['roadAddress'].split()
                filtered_road_address = ' '.join(road_address_parts[1:])  # 00특별시 제외

                # address가 filtered_road_address를 포함하는지 확인
                if filtered_road_address in df.loc[df['name'] == name, 'address'].values[0]:
                  mapx = int(item['mapx']) / 10000000
                  mapy = int(item['mapy']) / 10000000
                  mapx_list.append(mapx)
                  mapy_list.append(mapy)
                  found = True
                  break
           else:
           		# 이하생략...
                  
df['mapx'] = mapx_list
df['mapy'] = mapy_list
                
  • 출력된 최대 5개 결과들 중에 roadAddress 값이 csv파일에 저장된 주소값(강남구 테헤란로...이하 생략)에 포함되는지 확인한다. (굳이 서울특별시 부분을 자른 이유는 csv파일에 저장된 주소값에는 특별시 부분이 없었기 때문)

  • mapx, mapy값을 숫자로 변환하고 10000000을 나눠서 소수점을 만들어주고 리스트에 추가한다.

  • 결과가 없거나 해당하는 결과를 찾지 못했으면 csv파일에 저장된 가게이름과 주소값 일부(강남구.. 필요하다면 테헤란로까지)를 함께 검색해서 이 과정을 반복한다.

  • 이렇게 거르면 가게가 폐업해서 검색결과가 없지 않은 이상 전부 변환 가능하다.


결과

하이디라오 코엑스
127.0575397,37.5120151

파파야리프 코엑스점
127.0578213,37.5115087

이렇게하면 가게 고유의 좌표값을 불러 올 수 있다.


※ 제대로 된 값을 불러온 건지 확인하고 싶다면
네이버 지도에서 위/경도값으로 지도를 불러올 수 있는 방법이 있다.

https://map.naver.com/?lng={lng값}&lat={lat값}&title={표시하고 싶은 텍스트}


이 상태로 하이디라오 코엑스 점을 다시 검색하면

동일한 위치인 걸 확인 가능


참고
https://anweh.tistory.com/42
https://velog.io/@cyseok123/Spring-%EB%84%A4%EC%9D%B4%EB%B2%84-%EC%A7%80%EC%97%AD-%EA%B2%80%EC%83%89-API-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

profile
더 성장하자.

0개의 댓글