반응형
Geopy는 파이썬에서 지리 정보를 쉽게 다룰 수 있게 해주는 강력한 라이브러리입니다. 주소를 좌표로 변환하거나, 두 지점 간의 거리를 계산하는 등 다양한 지리 정보 처리가 가능합니다.
기본 설치 및 설정
# 설치
pip install geopy
# 기본 임포트
from geopy.geocoders import Nominatim
from geopy.distance import geodesic
from geopy.exc import GeocoderTimedOut
주소를 좌표로 변환하기 (Geocoding)
from geopy.geocoders import Nominatim
def get_coordinates(address: str):
# 지오코더 초기화
geolocator = Nominatim(user_agent="my_app")
try:
# 주소로 위치 검색
location = geolocator.geocode(address)
if location:
return {
'address': location.address,
'latitude': location.latitude,
'longitude': location.longitude
}
return None
except GeocoderTimedOut:
return None
# 사용 예시
address = "서울특별시 강남구 테헤란로 427"
coordinates = get_coordinates(address)
print(coordinates)
좌표로 주소 찾기 (Reverse Geocoding)
def get_address(latitude: float, longitude: float):
geolocator = Nominatim(user_agent="my_app")
try:
location = geolocator.reverse((latitude, longitude))
return location.address
except GeocoderTimedOut:
return None
# 사용 예시
latitude = 37.5665
longitude = 126.9780
address = get_address(latitude, longitude)
print(address)
두 지점 간의 거리 계산
from geopy.distance import geodesic
def calculate_distance(point1: tuple, point2: tuple):
"""
두 지점 간의 거리를 킬로미터 단위로 계산
point1, point2: (latitude, longitude) 형식의 튜플
"""
distance = geodesic(point1, point2).kilometers
return round(distance, 2)
# 사용 예시
seoul = (37.5665, 126.9780)
busan = (35.1796, 129.0756)
distance = calculate_distance(seoul, busan)
print(f"서울-부산 거리: {distance}km")
다양한 지오코더 활용
from geopy.geocoders import Nominatim, GoogleV3, ArcGIS
class GeocodingService:
def __init__(self, service='nominatim', api_key=None):
if service == 'nominatim':
self.geolocator = Nominatim(user_agent="my_app")
elif service == 'google':
self.geolocator = GoogleV3(api_key=api_key)
elif service == 'arcgis':
self.geolocator = ArcGIS()
else:
raise ValueError("Unsupported geocoding service")
def geocode(self, address):
try:
location = self.geolocator.geocode(address)
if location:
return {
'address': location.address,
'latitude': location.latitude,
'longitude': location.longitude
}
except Exception as e:
print(f"Error: {e}")
return None
실전 활용 예시: 주변 장소 찾기
def find_nearby_locations(center_point: tuple, locations: list, max_distance: float):
"""
주어진 중심점으로부터 특정 거리 내의 장소들을 찾습니다.
Args:
center_point: (latitude, longitude) 형식의 중심점
locations: [(name, lat, lon)] 형식의 장소 리스트
max_distance: 최대 거리 (km)
"""
nearby = []
for name, lat, lon in locations:
point = (lat, lon)
distance = calculate_distance(center_point, point)
if distance <= max_distance:
nearby.append({
'name': name,
'distance': distance,
'coordinates': point
})
return sorted(nearby, key=lambda x: x['distance'])
# 사용 예시
my_location = (37.5665, 126.9780)
places = [
("명동", 37.5634, 126.9850),
("강남역", 37.4980, 127.0278),
("이태원", 37.5340, 126.9940)
]
nearby_places = find_nearby_locations(my_location, places, 5.0)
for place in nearby_places:
print(f"{place['name']}: {place['distance']}km")
에러 처리와 최적화
from functools import lru_cache
import time
class GeocodingManager:
def __init__(self, retry_count=3, retry_delay=1):
self.geolocator = Nominatim(user_agent="my_app")
self.retry_count = retry_count
self.retry_delay = retry_delay
@lru_cache(maxsize=100)
def geocode_with_retry(self, address: str):
"""
주소 검색을 재시도하며 결과를 캐싱합니다.
"""
for attempt in range(self.retry_count):
try:
location = self.geolocator.geocode(address)
if location:
return {
'address': location.address,
'latitude': location.latitude,
'longitude': location.longitude
}
except GeocoderTimedOut:
if attempt < self.retry_count - 1:
time.sleep(self.retry_delay)
continue
except Exception as e:
print(f"Error: {e}")
break
return None
유용한 지리 정보 처리 유틸리티
def get_bounding_box(center: tuple, radius_km: float):
"""
중심점으로부터 특정 반경의 경계 상자를 계산합니다.
"""
from math import radians, degrees, cos, sin, asin, sqrt
lat, lon = center
radius = radius_km / 111.32 # 1도당 약 111.32km
min_lat = lat - radius
max_lat = lat + radius
# 위도에 따른 경도 범위 조정
radius_lon = radius / cos(radians(lat))
min_lon = lon - radius_lon
max_lon = lon + radius_lon
return {
'min_lat': min_lat,
'max_lat': max_lat,
'min_lon': min_lon,
'max_lon': max_lon
}
# 사용 예시
seoul_center = (37.5665, 126.9780)
search_area = get_bounding_box(seoul_center, 5.0) # 5km 반경
Geopy는 지리 정보 처리에 필수적인 도구이며, 특히 위치 기반 서비스를 개발할 때 매우 유용합니다. API 제한과 에러 처리에 주의하면서 사용하면 효과적인 지리 정보 처리 시스템을 구축할 수 있습니다.
'파이썬 > Basic' 카테고리의 다른 글
lru_cache : 캐싱 메모리 (0) | 2025.02.08 |
---|---|
함수 하나로 여러 가지 처리하기? Python 오버로딩 (2) | 2024.12.27 |
자료구조 : deque, Queue, heapq (0) | 2024.12.10 |
next()와 제너레이터 표현식 (1) | 2024.12.09 |
순환 참조(Circular Import) 이해하기와 해결 방법 (2) | 2024.12.06 |