selenium으로 네이버 최단거리 탐색

전윤환·2022년 5월 2일
0

파이썬 삽질하기

목록 보기
1/4

나는 왜 데이터를 뽑는데 셀레니움을 쓰는가?

원래는 퇴사 후 몇주 쉬다가 코딩 공부를 하려고 했다.
그런데 오늘 회사에서 연봉을 올려주고, 교육비를 지원해줄테니 같이 가잔다.
그러면서 이번에 제안서를 작성해야 하는데, 로우데이터가 필요하다고 한다. 그러니 다음주에 회의 좀 하자고 한다.
... 쉽게 하고 싶어서 네이버클라우드에 등록도 하고, api도 생성했는데!
쓰는 법을 모른다 ㅎㅎㅎㅎ 멍청해 ㅎㅎㅎㅎㅎㅎ
멍청하다고 코딩 하지 말란 법 있나? 일단 구글링하면서 진행해보자
(이 늦은 밤에 장염때문에 땀 뻘뻘 흘리고 있다. 죽을맛이다.)

셀레니움 필수코드(4버전)

import pandas as pd
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
import time
import pyautogui
import pyperclip

# 크롬 드라이버 자동업데이트
from webdriver_manager.chrome import ChromeDriverManager

df = pd.read_csv(f"D:\\file.csv")
# print(df)

# 네이버 길찾기 사이트 url
url = r'https://map.naver.com/v5/directions/-/-/-/car?c=14178840.5976907,4348447.5367843,15,0,0,0,dh'


# 브라우저 꺼짐 방지코드
chrome_options = Options()
chrome_options.add_experimental_option("detach", True)

# 불필요한 에러메세지 없애기
chrome_options.add_experimental_option("excludeSwitches", ['enable-logging'])

service = Service(executable_path=ChromeDriverManager().install())
# 크롬드라이버매니저를 통해 크롬드라이버를 설치하고 최신버전을 알아서 가져옴. 그 다음 서비스객체를 만들어서 서비스라는 객체에 저장

driver = webdriver.Chrome(service=service, options=chrome_options)

driver.implicitly_wait(10) # 웹페이지가 로딩될때까지 5초간 기다림
driver.maximize_window() # 화면을 최대화 시키는 명령어
driver.get(url) # 크롬창 띄우기

pandas는 거리탐색을 위한 출발지 목록을 csv로 저장했기 때문에 임포트함

기초 데이터 생성 1 - 판다스로 csv파일의 매장명, 주소 불러오기


위와 같이 csv파일이 저장돼있으므로, 데이터를 내 입맛에 맞게 바꾼다.

a_list = []
# print(df.iloc[0])

for i in range(0, 3, 1):
    a_name = df.iloc[i]['매장명']
    a_add = df.iloc[i]['전체주소']
    if a_name != '매장명':
        a_list.append({'매장명': a_name, '매장주소' : a_add})

맨 윗줄이 매장 정보가 아닌 컬럼명이라서 if문으로 솎아내준다.

데이터가 천개가 넘기 때문에, 코딩중일땐 range를 설정해서 3개만 뽑아본다.
맨 마지막에 range(len(a_list))로 변경할 예정이다.

기초 데이터 생성 2 - 센터와 셀레니움 코드

# 함수 설정해서 셀레니움으로 거리 돌리기
# 매장명, 매장주소, 센터명, 센터주소, 센터와의 거리, 근접센터

# 센터 주소
centers = [{'센터명' : '고양센터', '센터주소': '경기도 고양시'}, {'센터명': '화성센터', '센터주소': '경기도 화성시'}, {'센터명' : '천안센터', '센터주소': '충청남도 천안시'}, {'센터명': '대구센터', '센터주소': '경상북도 칠곡군'}, {'센터명': '제주센터', '센터주소': '제주특별자치도 제주시'}]
# 제주센터는 무조건 맨 마지막일 것
driver.implicitly_wait(10) # 웹페이지가 로딩될때까지 5초간 기다림
driver.maximize_window() # 화면을 최대화 시키는 명령어
driver.get(url) # 크롬창 띄우기

제주센터를 맨 마지막으로 두려는 이유는.... 우리회사 제주센터와 강원도에 있는 매장과의 거리를 굳이 계산할 필요가 없기 때문에, 나중에 if문으로 주소가 제주도인 매장에 대해서만 제주센터와의 거리를 잴 생각이기 때문이다.

맨 밑의 세 줄은 셀레니움을 쓰는 코드이므로 헷갈리지 말자.

함수 정의와 셀레니움 코드

def find_path(매장명, 매장주소):
    start = driver.find_element(By.CSS_SELECTOR, "#directionStart0") #출발지 셀렉터
    driver.implicitly_wait(10) # 10초 대기
    start.click() # 출발지 클릭
    start.send_keys(매장주소) # 출발지: 
    time.sleep(1)
    pyautogui.press('enter')
    time.sleep(2)

find_path라는 함수를 설정. 여기서 클래스를 쓸 수 있지 않나? 했는데 난 아직 클래스도 모르는 허접이니까 넘어가자.
find_element(By.CSS_SELECTOR, "#셀렉터") 외에 다른 모든 find 종류는 셀레니움4에서 다 사장됐다고 한다.

함수 내부(for문과 셀레니움 조합)

if a_list[i]['매장주소'][:2] != '제주':
        res_m_name = a_list[i]['매장명']
        res_m_addr = a_list[i]['매장주소']
        for x in range(len(centers)-1):
            res_cen_name = centers[x]['센터명']
            res_cen_addr = centers[x]['센터주소']
            destination = driver.find_element(By.CSS_SELECTOR, "#directionGoal1")
            destination.click() # 도착지 클릭
            destination.send_keys(res_cen_addr) # 도착지 주소 입력
            time.sleep(2)
            pyautogui.press('enter')
            time.sleep(2)
            pyautogui.press('enter')
            find_btn = driver.find_element(By.CSS_SELECTOR, '#container > shrinkable-layout > div > directions-layout > directions-result > div.main > div.search_area > directions-search > div.btn_box > button.btn.btn_direction')
            find_btn.click() # 길찾기 버튼 클릭
            time.sleep(4) # 4초간 대기
            distance = driver.find_element(By.XPATH, '//*[@id="container"]/shrinkable-layout/div/directions-layout/directions-result/div[1]/directions-summary-list/directions-hover-scroll/div/ul/li[1]/directions-summary-item-car/directions-summary-item-car-card/div[1]/div[1]/span/readable-distance')
            dis = str(distance.text) # 거리수 검색
            res_dis = dis.split('km')[0]
            res_all = [{'매장명': res_m_name, '매장주소' : res_m_addr, '센터명': res_cen_name, '센터주소': res_cen_addr, '거리': res_dis}]
            nearst = res_all[0]['거리']
            for iii in range(len(res_all)):
                if res_all[iii]['거리'] < nearst:
                    nearst = res_all[iii]['거리']
            destination.click() # 여기부터 도착지 삭제
            pyautogui.hotkey('ctrl', 'a')
            pyautogui.hotkey('delete')
            time.sleep(1)
        res_nearst = [{'매장명': res_all[iii]['매장명'], '매장주소':res_all[iii]['매장주소'], '센터명': res_all[iii]['센터명'], '센터주소': res_all[iii]['센터주소'], '거리': res_all[iii]['거리']}]
        print(res_nearst)

지금 봐도 어지럽네. 이게 뭐야? 진짜 한심한 코드네

위에서 정의한 함수 실행

for i in range(len(a_list)):
    find_path(a_list[i]['매장명'], a_list[i]['매장주소'])


오카이~~ 내가 원하는 데이터를 뽑아내는데 성공했다.

이제 이 데이터들을 엑셀에 저장해보려고 한다.
이건 다음 시리즈에서...

profile
코딩 연습장. 발전하고 싶습니다. 모든 방향에서의 비판 부탁드립니다.

0개의 댓글