프로젝트 중 네이버 지도 정보가 필요하여 크롤링하였다. 코드는 아래를 참고하였다.
하지만 아래와 같이 짝수번째 값만 에러가 발생하였고, 상호명은 출력되지만 주소만 출력이 되지않아서 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 = '경주 쫀드기' # 검색어
# css 찾을때 까지 10초대기
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)
dict_temp = {
'name': store_name,
'road_address': road_address,
}
store_dict['가게 정보'].append(dict_temp)
sleep(1)
# 다음 페이지 버튼 누를 수 없으면 종료
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)
'웹크롤링' 카테고리의 다른 글
[웹크롤링] 구글맵 크롤링하기 (Selenium) (0) | 2024.07.17 |
---|---|
[파이썬 웹크롤링] 네이버 블로그 크롤링하는 법, 페이지 구분하는 법 (0) | 2024.07.12 |