Selenium 설치
- 윈도우, mac(intel) : conda install selenium
- mac(m1) : pip install selenium
chromedriver
Beautiful Soup 만으로 해결할 수 없는 것
- 접근할 웹 주소를 알 수 없을 때
- 자바 스크립트를 사용하는 웹페이지의 경우
- 웹 브라우저로 접근하지 않으면 안될 때
Selenium
- 웹 브라우저로 원격 조작하는 도구
- 자동으로 URL을 열고 클릭 등이 가능
- 스크롤, 문자의 입력, 화면 캡처 등등
driver.quit() : 크롬 드라이버로 켠 창 끄기
#!pip install selenium
!pip install webdriver_manager
# !pip uninstall -y selenium # 셀레니움 삭제
from selenium import webdriver
#from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
# driver = webdriver.Chrome("../driver/chromedriver.exe") # 크롬 드라이버의 경로 지정
#driver = webdriver.Chrome(service = Service(ChromeDriverManager().install()))
# webdriver 경고문 해결 방법 : https://yeko90.tistory.com/entry/%EC%85%80%EB%A0%88%EB%8B%88%EC%9B%80-%EA%B8%B0%EC%B4%88-executablepath-has-been-deprecated-please-pass-in-a-Service-object-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95
#driver.get("https://www.naver.com") # driver.get() : get명령으로 접근하고 싶은 주소 설정
driver = webdriver.Chrome('../driver/chromedriver.exe') # mac : '../driver/chromedriver'
driver.get('https://www.naver.com')
driver.quit() # driver.quit() : 크롬 드라이버로 켠 창 끄기
from selenium import webdriver
from selenium.webdriver.chrome.options import Options #브라우저 창꺼짐 방지를 위한 모듈
from selenium.webdriver.common.by import By
# 브라우저 꺼짐 방지 옵션
# https://rimeestore.tistory.com/entry/%EC%85%80%EB%A0%88%EB%8B%88%EC%9B%80-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EA%B0%80-%EA%B3%84%EC%86%8D-%EA%BA%BC%EC%A7%88-%EB%95%8C
chrome_options = Options()
chrome_options.add_experimental_option("detach", True)
# 페이지 접근
# options=chrome_options : 브라우저 창꺼짐 방지 옵션 적용
url = 'https://www.opinet.co.kr/searRgSelect.do'
driver = webdriver.Chrome('../driver/chromedriver.exe') # mac : '../driver/chromedriver'
driver.get(url)
# 팝업창 화면 전환 후 닫아주기 ★
# switch_to.window()로 변경됨(https://m.blog.naver.com/tkdtjdtkddms/221976262160)
driver.switch_to.window(driver.window_handles[-1])
driver.close() # 팝업창이 없을 경우에는 창이 꺼지니 주의해야 함
driver.get(url)
import time
# def main_get() 으로 함수로 적용해도 됨, 다만, 여기서는 해보니, 함수 안에 driver가 선언되어 그 후에 적용이 안되었음..ㅠㅠ
# 페이지 접근 2 (하나의 코드로 진행)
url = 'https://www.opinet.co.kr/searRgSelect.do'
driver = webdriver.Chrome('../driver/chromedriver.exe',options=chrome_options)
# mac : '../driver/chromedriver'
# options=chrome_options : 브라우저 창꺼짐 방지 옵션 적용
driver.get(url)
time.sleep(3) # 페이지 띄운 후 3초 정지
# 팝업창으로 전환
#driver.switch_to.window(driver.window_handles[-1])
# 팝업창 닫아주기
#driver.close()
time.sleep(3) # 페이지 띄운 후 3초 정지
# 메인화면 창으로 전환
#driver.switch_to.window(driver.window_handles[-1])
# 접근 URL 다시 요청
driver.get(url)
#main_get()
# 지역 : 시/도
sido_list_raw = driver.find_element(By.ID, 'SIDO_NM0')
sido_list_raw.text
# .find_elements(By.TAG_NAME, 'option') : tag 이용하기
sido_list = sido_list_raw.find_elements(By.TAG_NAME, 'option')
len(sido_list), sido_list[1].text
# get_attribute() : 속성 값 가져오기
sido_list[1].get_attribute('value')
sido_names=[]
for option in sido_list:
sido_names.append(option.get_attribute('value'))
# 한줄 코드
#sido_names = [option.get_attribute('value') for option in sido_list]
sido_names
# 맨 앞 '' 빈칸 데이터 없애기
sido_names = sido_names[1:]
sido_names
sido_names[0]
# 웹 페이지의 시/도 변경 (서울)
sido_list_raw.send_keys(sido_names[0])
# 지역 : 시/군/구
gu_list_raw = driver.find_element(By.ID,'SIGUNGU_NM0') # 부모 태그
gu_list = gu_list_raw.find_elements(By.TAG_NAME,'option') # 자식 태그
gu_names = [option.get_attribute('value') for option in gu_list]
gu_names = gu_names[1:]
len(gu_names)
gu_list_raw.send_keys(gu_names[15])
# 엑셀 저장
#driver.find_element(By.CSS_SELECTOR, '#glopopd_excel').click()
#driver.find_element(By.XPATH, '//*[@id="glopopd_excel"]').click()
element_get_excel = driver.find_element(By.ID,'glopopd_excel')
element_get_excel.click()
# 서울, 25개의 구 주유소 데이터 다운
import time
from tqdm import tqdm_notebook
for gu in tqdm_notebook(gu_names):
element = driver.find_element(By.ID,'SIGUNGU_NM0')
element.send_keys(gu)
time.sleep(3)
element_get_excel = driver.find_element(By.XPATH, '//*[@id="glopopd_excel"]').click()
time.sleep(3)
driver.close()
import pandas as pd
from glob import glob
# !pip install glob
# 파일 목록 한 번에 가져오기
# glob() : 파일 목록 한번에 가져오기
glob('../data/지역_*.xls')
# 파일명 저장
stations_files = glob('../data/지역_*.xls')
stations_files
# 하나만 읽어보기
tmp = pd.read_excel(stations_files[0], header = 2)
# 엑셀 파일에 1, 2행에 데이터가 없어서 header = 2 설정
tmp.tail(2)
tmp_raw = []
for file_name in stations_files:
tmp = pd.read_excel(file_name, header = 2)
tmp_raw.append(tmp)
# concat() : 여러 개의 동일한 dataframe 붙이기
station_raw = pd.concat(tmp_raw)
station_raw
station_raw.info()
stations = pd.DataFrame(
{
"상호" : station_raw["상호"],
"주소" : station_raw["주소"],
"가격" : station_raw["휘발유"],
"셀프" : station_raw["셀프여부"],
"상표" : station_raw["상표"]
})
stations.head()
stations["주소"][0]
for eachAddress in stations["주소"]:
print(eachAddress.split()[1])
stations["구"] = [ eachAddress.split()[1] for eachAddress in stations["주소"]]
stations["구"].unique(), len(stations["구"].unique())
# stations[stations["구"] == "서울특별시"]
# stations.loc[stations["구"] =="서울특별시","구"] = "성동구"
# stations[stations["구"] == "특별시"]
# stations.loc[stations["구"] =="특별시","구"] = "도봉구"
# stations["구"].unique(), len(stations["구"].unique())
# 가격 데이터형 변환 object → float
# astype() : 데이터형 변환
stations["가격"] = stations["가격"].astype("float")
# 가격 정보가 없는 주유소 확인
stations[stations["가격"] == "-"]
# 가격 정보가 있는 주유소만 사용
stations = stations[stations["가격"] != '-']
stations.tail()
stations.info()
stations
# 인덱스 재정렬
stations.reset_index(inplace=True)
stations.tail()
stations.head()
del stations["index"]
stations.head()
import matplotlib.pyplot as plt
import seaborn as sns
import platform
from matplotlib import font_manager, rc
get_ipython().run_line_magic("matplotlib", "inline")
# %matplotlib inline
path = "C:/Windows/Fonts/malgun.ttf"
if platform.system() == "Darwin": # mac일 경우 한글 설정
rc("font", family="Arial Unicode MS")
elif platform.system() == "Windows": #window일 경우 한글 설정
font_name = font_manager.FontProperties(fname=path).get_name()
rc("font", family = font_name)
else:
print("Unknown system. sorry")
# boxplot(pandas)
stations.boxplot(column="가격", by="셀프", figsize=(12,8));
# boxplot(seabon)
plt.figure(figsize=(12, 8))
sns.boxplot(x="셀프", y="가격", data = stations, palette = "Set3")
plt.grid(True)
plt.show()
# 상표별 가격
# boxplot(seabon)
plt.figure(figsize=(12, 8))
sns.boxenplot(x="상표", y="가격", hue="셀프", data=stations, palette="Set3")
plt.grid()
plt.show()
# 지도 시각화
import json
import folium
import warnings
warnings.simplefilter(action="ignore", category=FutureWarning)
# 가장 비싼 주유소 10개
stations.sort_values(by="가격", ascending=False).head(10)
# 가장 싼 주유소 10개
stations.sort_values(by="가격", ascending=True).head(10)
import numpy as np
gu_data = pd.pivot_table(data=stations, index="구", values="가격", aggfunc=np.mean)
gu_data.head()
geo_path = "../data/02. skorea_municipalities_geo_simple.json"
geo_str = json.load(open(geo_path, encoding="utf-8"))
my_map = folium.Map(location=[37.5502, 126.982], zoom_start=10.5, tiles="Stamen Toner")
my_map.choropleth(
geo_data=geo_str,
data = gu_data,
columns=[gu_data.index, "가격"],
key_on="feature.id",
fill_color="PuRd"
)
my_map
💻 출처 : 제로베이스 데이터 취업 스쿨