▷ 오늘 학습 계획: EDA 강의(유가분석 3~5)
- 사이트 구조 확인
- 목표: 서울시 주유소를 대상으로 셀프 주유소가 저렴한지 확인
- 목표 데이터: 브랜드, 가격, 셀프 주유 여부, 위치
from selenium import webdriver from selenium.webdriver.common.by import By
페이지 접근
url = "https://www.opinet.co.kr/searRgSelect.do" driver = webdriver.Chrome("../driver/chromedriver.exe") driver.get(url) driver.get(url) #메인 페이지로 접속되어, 해당 URL로 다시 접근하기
팝업창이 뜰 경우
driver.switch_to.window(driver.window_handles[-1]) #팝업창으로 화면 전환 driver.close() #팝업창 닫기 driver.get(url) #접근 페이지 다시 요청
함수
import time def main_get(): #페이지 접근 url = "https://www.opinet.co.kr/searRgSelect.do" driver = webdriver.Chrome("../driver/chromedriver.exe") driver.get(url) time.sleep(3) #1_팝업창으로 화면 전환 driver.switch_to.window(driver.window_handles[-1]) #2_팝업창만 닫기 driver.close() time.sleep(3) #메인화면 창으로 전환 driver.switch_to.window(driver.window_handles[-1]) #접근 URL 다시 요청 driver.get(url)
지역(시/도) 리스트 확인
sido_list_raw = driver.find_element(By.ID, "SIDO_NM0") sido_list_raw.text
sido_list = sido_list_raw.find_elements(By.TAG_NAME, "option") len(sido_list) #18개 시/도 데이터 sido_list[1].text #서울 sido_list[1].get_attribute("value") #서울특별시
지역(시/도) 리스트 가져오기
#1 sido_names = [] for option in sido_list: sido_names.append(option.get_attribute("value")) sido_names #2 list comprehension sido_names = [option.get_attribute("value") for option in sido_list] sido_names[:5] #인덱스 0에 해당하는 값이 빈칸이여서 삭제하기 sido_names = sido_names[1:] #sido_names.remove("")
지역을 '서울'로 지정하기
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) #25개
시/군/구 지정
gu_list_raw.send_keys(gu_names[10])
엑셀 파일로 저장하기
#1 driver.find_element(By.CSS_SELECTOR, "#glopopd_excel").click() #2 driver.find_element(By.XPATH, '//*[@id="glopopd_excel"]').click() #3 element_get_excel = driver.find_element(By.ID, "glopopd_excel") element_get_excel.click()
모든 구의 데이터를 엑셀 파일로 저장
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)
import pandas as pd from glob import glob glob("../data/지역_*.xls") #파일 목록 한번에 가져오기
파일명 저장
stations_files = glob("../data/지역_*.xls")
파일 하나만 읽어보기
tmp = pd.read_excel(stations_files[0], header = 2) tmp.tail(2)
concat(형식이 동일하고 연달아 붙이기만 하면 될 때)
tmp_raw = [] for file_name in stations_files: tmp = pd.read_excel(file_name, header=2) tmp_raw.append(tmp) stations_raw = pd.concat(tmp_raw)
데이터 컬럼 생성하기
stations_raw.info() stations_raw.columns stations = pd.DataFrame({ "상호" : stations_raw["상호"], "주소" : stations_raw["주소"], "가격" : stations_raw["휘발유"], "셀프" : stations_raw["셀프여부"], "상표" : stations_raw["상표"] }) stations.tail()
주소에서 '구' 정보만 가져오기
for eachAddress in stations["주소"]: print(eachAddress.split()[1]) stations["구"] = [eachAddress.split()[1] for eachAddress in stations["주소"]]
'구' 데이터 확인하기
stations["구"].unique(), len(stations["구"].unique())
'가격' object -> float 형변환 오류
stations["가격"] = stations["가격"].astype("float") #ValueError: could not convert string to float: '-'
가격 정보가 없는 주유소 확인
stations[stations["가격"] == "-"]
가격 정보가 있는 주유소만 사용하기
stations = stations[stations["가격"] != "-"] stations["가격"] = stations["가격"].astype("float") #가격 데이터 형변환
인덱스 재정렬
stations.reset_index(inplace = True) stations.tail() del stations["index"] #재정렬 하면서 index 컬럼이 또 생겨서 삭제
matplotlib 한글 대응
import matplotlib.pyplot as plt
import seaborn as sns
import platform
from matplotlib import font_manager, rc
get_ipython().run_line_magic("matplotlib", "inline")
path = "C:/Windows/Fonts/malgun.ttf"
if platform.system() == "Darwin":
rc("font", family = "Arial Unicod MS")
elif platform.system() == "Windows":
font_name = font_manager.FontProperties(fname=path).get_name()
rc("font", family=font_name)
else:
print("Unknown system")
pandas boxplot
- Median을 중심으로 아래 위 상자가 각각 전체 데이터의 25%씩, 총 50%를 가진다.
- 상자 전체 길이를 IQR(Inter Quatile Range)라고 한다.
- IQR의 1.5배 이상 벗어나면 점으로 별도 표기(outlier)
stations.boxplot(column="가격", by="셀프", figsize = (12,8));
seaborn boxplot
plt.figure(figsize=(12,8)) sns.boxplot(x="셀프", y="가격", data=stations, palette = "Set3") plt.grid(True) plt.show()
상표 별 가격 분포(셀프 주유 여부 포함)
plt.figure(figsize=(12,8)) sns.boxplot(x="상표", y="가격", hue="셀프", data=stations, palette = "Set3") plt.grid(True) plt.show()
import json import folium import warnings #경고 문구 안나오게 설정 warnings.simplefilter(action="ignore", category=FutureWarning)
가격에 따른 주유소 정렬
stations.sort_values(by="가격", ascending=False).head(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()
choropleth
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
📝 selenium 안내사항에서 코드 변경 사항을 봤는데 강의 들으면서 아무 생각 없이 이전 코드를 따라 적었다. 에러가 나서 한참 고민했는데 바뀐 코드로 썼더니 바로 실행됐다. 이전 코드를 보니까 더 헷갈리는거 같다.
from selenium.webdriver.common.by import By driver.find_element(By.ID, "SIDO_NM0")
▷ 내일 학습 계획: EDA 강의(Naver API)