[웹크롤링] 네이버지도 크롤링 (+ 유의점)

2024. 7. 20. 14:17·개발 | 프로젝트

프로젝트 중 네이버 지도 정보가 필요하여 크롤링하였다. 코드는 아래를 참고하였다. 

https://velog.io/@kimdy0915/Selenium%EC%9C%BC%EB%A1%9C-%EB%84%A4%EC%9D%B4%EB%B2%84-%EC%A7%80%EB%8F%84-%ED%81%AC%EB%A1%A4%EB%A7%81%ED%95%98%EA%B8%B0 

 

하지만 아래와 같이 짝수번째 값만 에러가 발생하였고, 상호명은 출력되지만 주소만 출력이 되지않아서  addr을 따로 출력해보니 짝수번째만 리스트 값이 비어있었다. 

 


네이버 지도에서 다시 도로명 주소를 확인했더니 홀수, 짝수별로 클래스명이 달랐다 .. 확인을 안 하고 짝수 클래스명으로 접근해서 에러가 났던 것이었다.

 

네이버 지도 크롤링 전체 코드

추가적으로 위도, 경도 정보가 필요하여 geopy 라이브러리를 사용하였다.

import json
import time
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from webdriver_manager.chrome import ChromeDriverManager

driver = webdriver.Chrome(ChromeDriverManager().install())

from geopy.geocoders import Nominatim
geo_local = Nominatim(user_agent='South Korea')

# 위도, 경도 반환 함수
def geocoding(address):
    try:
        geo = geo_local.geocode(address)
        x_y = [geo.latitude, geo.longitude]
        return x_y

    except:
        return [0,0]

# 네이버 지도 검색 페이지 열기
driver.get("https://map.naver.com/v5/search")
key_word = '경주 쫀드기'  # 검색어

def time_wait(num, code):
    try:
        wait = WebDriverWait(driver, num).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, code)))
    except:
        print(code, '태그를 찾지 못하였습니다.')
        driver.quit()
    return wait

# frame 변경 메소드
def switch_frame(frame):
    driver.switch_to.default_content()  # frame 초기화
    driver.switch_to.frame(frame)  # frame 변경

# 페이지 다운
def page_down(num):
    body = driver.find_element(By.CSS_SELECTOR, 'body')
    body.click()
    for i in range(num):
        body.send_keys(Keys.PAGE_DOWN)

# css를 찾을때 까지 10초 대기
time_wait(10, 'div.input_box > input.input_search')

# 검색창 찾기
search = driver.find_element(By.CSS_SELECTOR, 'div.input_box > input.input_search')
search.send_keys(key_word)  
search.send_keys(Keys.ENTER) 

sleep(5)

# frame 변경
time_wait(10, 'iframe#searchIframe')
switch_frame('searchIframe')

sleep(5)

page_down(40)
sleep(2)

# 가게 리스트
store_list = driver.find_elements(By.CSS_SELECTOR, 'li.VLTHu')
# 페이지 리스트
next_btn = driver.find_elements(By.CSS_SELECTOR, '.zRM9F> a')

# dictionary 생성
store_dict = {'가게 정보': []}
# 시작시간
start = time.time()
print('[크롤링 시작...]')

# 크롤링 (페이지 리스트 만큼)
for btn in range(len(next_btn))[1:]:  # next_btn[0] = 이전 페이지 버튼 무시 -> [1]부터 시작
    store_list = driver.find_elements(By.CSS_SELECTOR, 'li.VLTHu')
    
    names = driver.find_elements(By.CSS_SELECTOR, '.YwYLL')  #  장소명
    for data in range(len(store_list)): 

        sleep(2)
        try:
            # 도로명 초기화
            road_address = ''
            # 가게명 가져오기
            store_name = names[data].text
            print(store_name)
        
            # 주소 버튼 누르기
            address_buttons = driver.find_elements(By.CSS_SELECTOR, '.lWwyx > a')
            address_buttons[data].click()

            
            # 로딩 기다리기
            sleep(2)

            # 주소 눌렀을 때 도로명, 지번 나오는 div
            addr = driver.find_elements(By.CSS_SELECTOR, '.AbTyi> div')
        
            sleep(2)
            # 도로명
            road = addr[0].text 
            road_address = road[3:-2]
        
            sleep(2)
            print({'id':data, 'title': store_name, 'address':road_address, 'lat':geocoding(road_address)[0],'lng':geocoding(road_address)[1]})
            # dict에 데이터 집어넣기
            dict_temp = {
                'name': store_name,
                'road_address': road_address,
                'latitude' : geocoding(road_address)[0]
                'longitude' : geocoding(road_address)[1]
                
            }
            store_dict['가게 정보'].append(dict_temp)
      
        except Exception as e:
            print(e)
            
    # 다음 페이지 버튼 누를 수 없으면 종료
    if not next_btn or not next_btn[-1].is_enabled():
        break

    if names[-1]:  # 마지막 가게일 경우 다음버튼 클릭
        next_btn[-1].click()
        sleep(2)

    else:
        print('페이지 인식 못함')
        break

print('[데이터 수집 완료]\n소요 시간 :', time.time() - start)
driver.quit()  # 작업이 끝나면 창을 닫는다.

# json 파일로 저장
#with open('data/geongjy_store_data.json', 'w', encoding='utf-8') as f:
 #   json.dump(store_dict, f, indent=4, ensure_ascii=False)

 

 

'개발 | 프로젝트' 카테고리의 다른 글

[Spring] MVC 동작 구조  (0) 2025.02.15
Node.js, Unity WebSocket 통신 (+ 에러 해결)  (0) 2025.02.13
[Google Cloud Platform] GCP Cloud SQL 구축, 외부 접속  (1) 2024.10.23
[웹크롤링] 구글맵 크롤링하기 (Selenium)  (0) 2024.07.17
[웹크롤링] 네이버 블로그 크롤링하는 법, 페이지 구분하는 법  (0) 2024.07.12
'개발 | 프로젝트' 카테고리의 다른 글
  • Node.js, Unity WebSocket 통신 (+ 에러 해결)
  • [Google Cloud Platform] GCP Cloud SQL 구축, 외부 접속
  • [웹크롤링] 구글맵 크롤링하기 (Selenium)
  • [웹크롤링] 네이버 블로그 크롤링하는 법, 페이지 구분하는 법
seulll
seulll
개인 공부 / 정리 블로그입니다
  • seulll
    seulll
    seulll
  • 전체
    오늘
    어제
    • 분류 전체보기 (330) N
      • 코딩테스트 (226) N
        • programmers (python) (156)
        • 백준 (python) (68) N
      • 자료구조 | 알고리즘 (14)
      • 개발 | 프로젝트 (40)
        • Python (4)
        • Java | Spring (7)
        • Android (4)
        • Unity (3)
        • API (4)
      • CS (15)
        • Network (5)
        • SQL (2)
        • OS (4)
      • 데이터 분석 (14)
      • 기타 (12)
  • 블로그 메뉴

    • 홈
    • 태그
    • 글쓰기
    • 설정
  • 링크

    • GitHub
  • 인기 글

  • 태그

    API
    confusion matrix
    오블완
    카카오맵 api
    solving environment
    오차행렬
    야근 지수
    프로그래머스
    kakao map api
    웹크롤링
    asterisk
    카카오맵
    파이썬
    티스토리챌린지
    바다코끼리
    모델 성능 평가
    박스플롯
    그리디 알고리즘
    대입 표현식
    프렌즈4블록
    Boxplot
    Python
    백엔드
    데이터분석
    코딩테스트
    2 x n 타일링
    Greedy
    백엔드 개발자
    train_test_split
    백엔드 개발자 역량
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
seulll
[웹크롤링] 네이버지도 크롤링 (+ 유의점)
상단으로

티스토리툴바