[Python]카카오맵 이름 주소 크롤링 및 지오코딩으로 위도, 경도 구하기

MINK·2023년 2월 14일
0
post-thumbnail

[Python]카카오맵 이름 주소 크롤링 및 지오코딩으로 위도, 경도 구하기

환경 : Intellij

언어 : Python

패키지 : Pandas, bs4, Selenium, Webdriver(ChromeDriver), Geopy

  1. BeautifulSoup, Selenium을 이용하여 카카오맵 크롤링

    • 여러 블로그를 참고하여 직접 완성한 코드이지만 카카오에서 html페이지 소스를 바꿀 수 있기때문에 참고만 하길 바람.!
    • 이용목적
      • 카카오프렌즈샵에선 오프라인 매장의 위치 혹은 길찾기 서비스가 없어서 클론코딩하면서 추가적으로 이런 서비스가 있으면 사용자가 온라인에서 팔 수 없었던 물품들을 오프라인 매장에서도 구매할 수 있는 편리함을 생각했다.

Kakaomap_Chrwaling.py

# 1. 패키지 설정(처음이라면 패키지를 설치할 것)
import time

import pandas as pd
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver import Keys
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.common.exceptions import ElementNotInteractableException

# 2. Driver & BeautifulSoup
driver = webdriver.Chrome(ChromeDriverManager().install())

# 3. 크롤링할 url을 설정
org_crawling_url = "https://map.kakao.com/"
driver.get(org_crawling_url)
time.sleep(2)

# 4. 검색창 소스
element = driver.find_element(By.CLASS_NAME, 'query.tf_keyword')

# 5. send_keys를 통해 검색창 입력설정
element.send_keys("카카오프렌즈샵")
time.sleep(2)

# 6. 팝업창 닫기
driver.find_element(By.CLASS_NAME, 'DimmedLayer').click()
time.sleep(2)

# 7. 검색실행
driver.find_element(By.CLASS_NAME, 'go.ico_search.btn_search.active').click()
time.sleep(2)

# 8. 장소 더보기(많은 장소들을 불러오기 위함)
driver.find_element(By.ID, 'info.search.place.more').click()
time.sleep(4)

# 9. 데이터를 넣을 공간 설정
addr1list = []
addr2list = []
namelist = []

page = 1

# 10. while문으로 page 차례대로 설정
# 검색하면 데이터는 총 2페이지
while page < 3:
    xPath = '//*[@id="info.search.page.no' + str(page) + '"]'
    try:
        print(page)
        driver.find_element(By.XPATH, xPath).send_keys(Keys.ENTER)
    except ElementNotInteractableException:
        print('End of Page')
        break
    time.sleep(3)
    place_lists = driver.find_elements(By.CLASS_NAME, 'PlaceItem.clickArea')
    # 장소리스트값들을 하나씩 select문으로 텍스트값을 저장 후 리스트에 추가
    for p in place_lists:
        store_html = p.get_attribute('innerHTML')
        store_info = BeautifulSoup(store_html, "html.parser")
        name = store_info.select('div.head_item.clickArea > strong > a.link_name')[0].text.strip()
        addr1 = store_info.select('div.info_item > div.addr > p')[0].text.strip()
        addr2 = store_info.select('div.info_item > div.addr > p.lot_number')[0].text.strip()
        namelist.append(name)
        addr1list.append(addr1)
        addr2list.append(addr2)
    page = page + 1


# 11. 데이터프레임 설정 후 csv로 저장    
data = {"name": namelist, "addr1": addr1list, "addr2": addr2list}
df = pd.DataFrame(data)
print(df)

# 12. kakaomap.csv 저장할 때 index값을 id로 설정해야 front에서 사용하기 좋음
df.to_csv("kakaomap.csv", encoding="utf-8-sig", index_label=['Id'])
  1. Geocoding을 이용하여 주소값을 위도 경도값으로 변경 후 dataframe에 행 추가
    • 왜 주소를 위도 경도로 바꿧는가?
      • 크롤링하다보면 주소값이 none으로 표시되어있는 곳도 있었다.
      • 지번과 주소가 정확하지않은 곳으로 찍혀서 지도에 표시할 때 어려움이 있었다.

Geocoding.py

# 1. 패키지 설정(처음이라면 패키지를 설치할 것)
from geopy.geocoders import Nominatim
import pandas as pd

# 2. kakaomap.csv 파일을 읽어온다.
addr = pd.read_csv("C:/Users/mink/PycharmProjects/pythonProject1/kakaomap.csv", encoding="utf-8") # cp949
# 데이터 확인
# print(addr)

# 리스트설정
latList = []
lngList = []

# 주소를 위도경도로 설정하는 함수
def geocoding(address):
    # Nomination을 이용하여 서비스객체에 대한 핸들러를 가져온다.
    geolocoder = Nominatim(user_agent='South Korea', timeout=None)
    # 위경도를 찾아야할 주소입력 설정 
    geo = geolocoder.geocode(address)
    crd = {"lat": str(geo.latitude), "lng": str(geo.longitude)}
    return crd

# 위도 경도 21번째 에러상태 공항로 2번길 위치 제대로 찾기
# 반복문을 통해 지번으로 위경도 구하고 리스트에 추가
for i in addr['addr2']:
	# print(i)
    latlng = geocoding(i)
	# print(latlng)
    lat = latlng['lat']
    lng = latlng['lng']
    latList.append(lat)
    lngList.append(lng)

# pd.Series와 Concat을 이용하여 행을 추가하고 csv파일로 저장
sr1 = pd.Series(latList, name='lat')
sr2 = pd.Series(lngList, name='lng')
addr1 = pd.concat([addr, sr1, sr2], axis=1)
print(addr1)
addr1.to_csv('kakaompa_latLng.csv', index=False)
profile
parkminkyu velog

0개의 댓글