-
EDA) 셀프 주유소 가격 분석EDA 2023. 3. 10. 23:01
04. Self Oil Station Price Analysis 04. Self Oil Station Price Analysis¶
1. 셀레니움 설치¶
In [ ]:conda install selenium
In [3]:from selenium import webdriver
In [6]:driver = webdriver.Chrome("../driver/chromedriver.exe") driver.get("http://www.naver.com")
In [7]:driver.quit()
2. 셀프 주유소가 정말 저렴한가요?¶
- 데이터 확보하기 위한 작업
- http://www.opinet.co.kr/searRgSelect.do
- 사이트 구조 확인
- 브랜드
- 가격
- 셀프 주유 여부
- 위치
3. 셀레니움으로 접근¶
In [61]:from selenium import webdriver
In [62]:# 페이지 접근 url = "http://www.opinet.co.kr/searRgSelect.do" driver = webdriver.Chrome("../driver/chromedriver.exe") driver.get(url)
- 문제: 해당 URL로 한번에 접근이 안됨
In [63]:driver.get(url)
In [47]:import time def main_get(): # 페이지 접근 url = "http://www.opinet.co.kr/searRgSelect.do" driver = webdriver.Chrome("../driver/chromedriver.exe") time.sleep(3) # 팝업창 화면 전환 후 닫아주기 driver.switch_to_window(driver.window_handles[-1]) # 팝업창 닫아주기 driver.close() time.sleep(3) # 메인화면 창으로 전환 driver.switch_to_window(driver.window_handles[-1]) # 접근 url로 다시 요청 driver.get()
In [64]:# 지역: 시/도 sido_list_raw = driver.find_element_by_id("SIDO_NM0") sido_list_raw.text
Out[64]:' 시/도\n \n \n \n 서울\n \n \n \n \n 부산\n \n \n \n \n 대구\n \n \n \n \n 인천\n \n \n \n \n 광주\n \n \n \n \n 대전\n \n \n \n \n 울산\n \n \n \n \n 세종\n \n \n \n 경기\n \n \n \n \n \n 강원\n \n \n \n \n 충북\n \n \n \n \n 충남\n \n \n \n \n 전북\n \n \n \n \n 전남\n \n \n \n \n 경북\n \n \n \n \n 경남\n \n \n \n \n 제주\n \n \n '
In [65]:sido_list = sido_list_raw.find_elements_by_tag_name("option") len(sido_list), sido_list[17].text
Out[65]:(18, '제주')
In [66]:# 속성값 데이터 호출 sido_list[1].get_attribute("value")
Out[66]:'서울특별시'
In [67]:sido_names = [] for option in sido_list: sido_names.append(option.get_attribute("value")) sido_names
Out[67]:['', '서울특별시', '부산광역시', '대구광역시', '인천광역시', '광주광역시', '대전광역시', '울산광역시', '세종특별자치시', '경기도', '강원도', '충청북도', '충청남도', '전라북도', '전라남도', '경상북도', '경상남도', '제주특별자치도']
In [68]:sido_names = [option.get_attribute("value") for option in sido_list] sido_names = sido_names[1:]
In [69]:sido_list_raw.send_keys(sido_names[0])
In [70]:# 구 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)
Out[70]:25
In [71]:gu_list_raw.send_keys(gu_names[15])
In [72]:# 엑셀 저장 driver.find_element_by_css_selector("#glopopd_excel").click()
In [74]:driver.find_element_by_xpath('//*[@id="glopopd_excel"]').click()
In [75]:element_get_excel = driver.find_element_by_id("glopopd_excel") element_get_excel.click()
In [77]: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_id("glopopd_excel").click() time.sleep(3)
C:\Users\admin\AppData\Local\Temp\ipykernel_26220\1864553744.py:4: TqdmDeprecationWarning: This function will be removed in tqdm==5.0.0 Please use `tqdm.notebook.tqdm` instead of `tqdm.tqdm_notebook` for gu in tqdm_notebook(gu_names):
0%| | 0/25 [00:00<?, ?it/s]
In [78]:driver.close()
4. 데이터 정리하기¶
In [79]:import pandas as pd from glob import glob
In [80]:# 파일 목록 한번에 가져오기 glob("../data/지역_*.xls")
Out[80]:['../data\\지역_위치별(주유소) (1).xls', '../data\\지역_위치별(주유소) (10).xls', '../data\\지역_위치별(주유소) (11).xls', '../data\\지역_위치별(주유소) (12).xls', '../data\\지역_위치별(주유소) (13).xls', '../data\\지역_위치별(주유소) (14).xls', '../data\\지역_위치별(주유소) (15).xls', '../data\\지역_위치별(주유소) (16).xls', '../data\\지역_위치별(주유소) (17).xls', '../data\\지역_위치별(주유소) (18).xls', '../data\\지역_위치별(주유소) (19).xls', '../data\\지역_위치별(주유소) (2).xls', '../data\\지역_위치별(주유소) (20).xls', '../data\\지역_위치별(주유소) (21).xls', '../data\\지역_위치별(주유소) (22).xls', '../data\\지역_위치별(주유소) (23).xls', '../data\\지역_위치별(주유소) (24).xls', '../data\\지역_위치별(주유소) (3).xls', '../data\\지역_위치별(주유소) (4).xls', '../data\\지역_위치별(주유소) (5).xls', '../data\\지역_위치별(주유소) (6).xls', '../data\\지역_위치별(주유소) (7).xls', '../data\\지역_위치별(주유소) (8).xls', '../data\\지역_위치별(주유소) (9).xls', '../data\\지역_위치별(주유소).xls']
In [81]:# 파일명 저장 stations_files = glob("../data/지역_*.xls") stations_files[:5]
Out[81]:['../data\\지역_위치별(주유소) (1).xls', '../data\\지역_위치별(주유소) (10).xls', '../data\\지역_위치별(주유소) (11).xls', '../data\\지역_위치별(주유소) (12).xls', '../data\\지역_위치별(주유소) (13).xls']
In [84]:# 하나만 읽어보기 tmp = pd.read_excel(stations_files[0], header=2) tmp.tail(2)
Out[84]:지역 상호 주소 상표 전화번호 셀프여부 고급휘발유 휘발유 경유 실내등유 12 서울특별시 천호현대주유소 서울 강동구 천중로 67 (천호동) 현대오일뱅크 02-484-9323 N - 1793 1794 - 13 서울특별시 광성주유소 서울 강동구 올림픽로 673 (천호동) S-OIL 02-470-5133 N - 1978 1968 1900 In [85]:tmp_raw = [] for file_name in stations_files: tmp = pd.read_excel(file_name, header=2) tmp_raw.append(tmp)
- 형식이 동일하고 연달아 붙이기만 하면 될 때는 concat
In [88]:stations_raw = pd.concat(tmp_raw) stations_raw
Out[88]:지역 상호 주소 상표 전화번호 셀프여부 고급휘발유 휘발유 경유 실내등유 0 서울특별시 재건에너지 재정제2주유소 고속셀프지점 서울특별시 강동구 천호대로 1246 (둔촌제2동) 현대오일뱅크 02-487-2030 Y - 1569 1572 - 1 서울특별시 구천면주유소 서울 강동구 구천면로 357 (암사동) 현대오일뱅크 02-441-0536 N - 1594 1575 - 2 서울특별시 (주)소모에너지 신월주유소 서울 강동구 양재대로 1323 (성내동) GS칼텍스 02-6956-6674 Y 1806 1596 1628 1650 3 서울특별시 대성석유(주)길동주유소 서울 강동구 천호대로 1168 GS칼텍스 02-474-7222 N 1825 1596 1638 1600 4 서울특별시 (주)삼표에너지 고덕주유소 서울 강동구 고덕로 39 (암사동) GS칼텍스 02-441-3327 Y 1815 1599 1659 1615 ... ... ... ... ... ... ... ... ... ... ... 28 서울특별시 대청주유소 서울 강남구 개포로 654 (일원동) SK에너지 02-445-5500 N 2466 2216 2196 1836 29 서울특별시 갤러리아주유소 서울 강남구 압구정로 426 SK에너지 02-540-4965 N 2488 2290 2288 1820 30 서울특별시 SK논현주유소 서울 강남구 논현로 747 (논현동) SK에너지 02-511-0955 N 2495 2290 2258 1835 31 서울특별시 (주)제이제이네트웍스 제이제이주유소 서울 강남구 언주로 716 현대오일뱅크 02-518-5631 N 2548 2348 2297 - 32 서울특별시 (주)만정에너지 삼보주유소 서울 강남구 봉은사로 433 (삼성동) GS칼텍스 02-518-5141 N 2818 2578 2540 1850 440 rows × 10 columns
In [92]:stations_raw.columns
Out[92]:Index(['지역', '상호', '주소', '상표', '전화번호', '셀프여부', '고급휘발유', '휘발유', '경유', '실내등유'], dtype='object')
In [95]:stations = pd.DataFrame({ "상호":stations_raw["상호"], "주소":stations_raw["주소"], "가격":stations_raw["휘발유"], "셀프":stations_raw["셀프여부"], "상표":stations_raw["상표"] } ) stations.tail()
Out[95]:상호 주소 가격 셀프 상표 28 대청주유소 서울 강남구 개포로 654 (일원동) 2216 N SK에너지 29 갤러리아주유소 서울 강남구 압구정로 426 2290 N SK에너지 30 SK논현주유소 서울 강남구 논현로 747 (논현동) 2290 N SK에너지 31 (주)제이제이네트웍스 제이제이주유소 서울 강남구 언주로 716 2348 N 현대오일뱅크 32 (주)만정에너지 삼보주유소 서울 강남구 봉은사로 433 (삼성동) 2578 N GS칼텍스 In [99]:stations["구"] = [eachAddress.split()[1] for eachAddress in stations["주소"]]
In [100]:stationsOut[100]:상호 주소 가격 셀프 상표 구 0 재건에너지 재정제2주유소 고속셀프지점 서울특별시 강동구 천호대로 1246 (둔촌제2동) 1569 Y 현대오일뱅크 강동구 1 구천면주유소 서울 강동구 구천면로 357 (암사동) 1594 N 현대오일뱅크 강동구 2 (주)소모에너지 신월주유소 서울 강동구 양재대로 1323 (성내동) 1596 Y GS칼텍스 강동구 3 대성석유(주)길동주유소 서울 강동구 천호대로 1168 1596 N GS칼텍스 강동구 4 (주)삼표에너지 고덕주유소 서울 강동구 고덕로 39 (암사동) 1599 Y GS칼텍스 강동구 ... ... ... ... ... ... ... 28 대청주유소 서울 강남구 개포로 654 (일원동) 2216 N SK에너지 강남구 29 갤러리아주유소 서울 강남구 압구정로 426 2290 N SK에너지 강남구 30 SK논현주유소 서울 강남구 논현로 747 (논현동) 2290 N SK에너지 강남구 31 (주)제이제이네트웍스 제이제이주유소 서울 강남구 언주로 716 2348 N 현대오일뱅크 강남구 32 (주)만정에너지 삼보주유소 서울 강남구 봉은사로 433 (삼성동) 2578 N GS칼텍스 강남구 440 rows × 6 columns
In [102]:stations["구"].unique(), len(stations["구"].unique())
Out[102]:(array(['강동구', '동대문구', '동작구', '마포구', '서대문구', '서초구', '성동구', '성북구', '송파구', '양천구', '영등포구', '강북구', '용산구', '은평구', '종로구', '중구', '중랑구', '강서구', '관악구', '광진구', '구로구', '금천구', '노원구', '도봉구', '강남구'], dtype=object), 25)In [132]:#가격 정보가 있는 주유소만 사용 stations = stations[stations["가격"] != "-"] # 가격 데이터형 변환 stations["가격"] = stations["가격"].astype("float")
In [133]:stations.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 439 entries, 0 to 438 Data columns (total 7 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 index 439 non-null int64 1 상호 439 non-null object 2 주소 439 non-null object 3 가격 439 non-null float64 4 셀프 439 non-null object 5 상표 439 non-null object 6 구 439 non-null object dtypes: float64(1), int64(1), object(5) memory usage: 27.4+ KB
In [141]:# 인덱스 재정렬 stations.reset_index(inplace=True)
In [143]:del stations["index"] stations
Out[143]:상호 주소 가격 셀프 상표 구 0 재건에너지 재정제2주유소 고속셀프지점 서울특별시 강동구 천호대로 1246 (둔촌제2동) 1569.0 Y 현대오일뱅크 강동구 1 구천면주유소 서울 강동구 구천면로 357 (암사동) 1594.0 N 현대오일뱅크 강동구 2 (주)소모에너지 신월주유소 서울 강동구 양재대로 1323 (성내동) 1596.0 Y GS칼텍스 강동구 3 대성석유(주)길동주유소 서울 강동구 천호대로 1168 1596.0 N GS칼텍스 강동구 4 (주)삼표에너지 고덕주유소 서울 강동구 고덕로 39 (암사동) 1599.0 Y GS칼텍스 강동구 ... ... ... ... ... ... ... 434 대청주유소 서울 강남구 개포로 654 (일원동) 2216.0 N SK에너지 강남구 435 갤러리아주유소 서울 강남구 압구정로 426 2290.0 N SK에너지 강남구 436 SK논현주유소 서울 강남구 논현로 747 (논현동) 2290.0 N SK에너지 강남구 437 (주)제이제이네트웍스 제이제이주유소 서울 강남구 언주로 716 2348.0 N 현대오일뱅크 강남구 438 (주)만정에너지 삼보주유소 서울 강남구 봉은사로 433 (삼성동) 2578.0 N GS칼텍스 강남구 439 rows × 6 columns
In [110]:stations.to_csv("../data/stations.csv",sep=",",encoding="utf8")
5. 주유 가격 정보 시각화¶
In [144]:import matplotlib.pyplot as plt import seaborn as sns import platform from matplotlib import font_manager, rc %matplotlib inline path = "C:/Windows/Fonts/malgun.ttf" if platform.system() == "Darwin": rc("font", family="Arial Unicode MS") elif platform.system() == "Windows": font_name = font_manager.FontProperties(fname=path).get_name() rc("font",family=font_name) else: print("Unknown system")
In [145]:# boxplot(feat. pandas) stations.boxplot(column="가격", by="셀프",figsize=(12,8))
Out[145]:<AxesSubplot: title={'center': '가격'}, xlabel='셀프'>In [146]:# boxplot(feat.seaborn) plt.figure(figsize=(12,8)) sns.boxplot(x="셀프",y="가격",data=stations,palette="Set3") plt.grid(True) plt.show()
In [147]:# boxplot(feat.seaborn) plt.figure(figsize=(12, 8)) sns.boxplot(x="상표", y="가격", hue="셀프", data=stations, palette="Set3") plt.grid(True) plt.show()
In [148]:# 지도 시각화 import json import folium import warnings warnings.simplefilter(action="ignore",category=FutureWarning)
In [149]:# 가장 비싼 주유소 10개 stations.sort_values(by="가격", ascending = False)
Out[149]:상호 주소 가격 셀프 상표 구 272 서남주유소 서울 중구 통일로 30 2684.0 N SK에너지 중구 237 서계주유소 서울 용산구 청파로 367 (청파동) 2679.0 N GS칼텍스 용산구 438 (주)만정에너지 삼보주유소 서울 강남구 봉은사로 433 (삼성동) 2578.0 N GS칼텍스 강남구 271 필동주유소 서울 중구 퇴계로 196 (필동2가) 2449.0 N GS칼텍스 중구 437 (주)제이제이네트웍스 제이제이주유소 서울 강남구 언주로 716 2348.0 N 현대오일뱅크 강남구 ... ... ... ... ... ... ... 112 (주)삼표에너지 정릉주유소 서울 성북구 보국문로 35 (정릉동) 1525.0 Y GS칼텍스 성북구 239 타이거주유소 서울 은평구 수색로 188 (증산동) 1524.0 Y SK에너지 은평구 164 삼미상사(주)신월IC셀프주유소 서울 양천구 중앙로 331 (신월동) 1524.0 Y SK에너지 양천구 163 (주)타이거오일 신정주유소 서울 양천구 중앙로 226 (신정동) 1519.0 Y SK에너지 양천구 238 다회주유소 서울 은평구 증산로 441 (신사동) 1519.0 Y S-OIL 은평구 439 rows × 6 columns
In [150]:# 가장 저렴한 주유소 10개 stations.sort_values(by="가격", ascending = True)
Out[150]:상호 주소 가격 셀프 상표 구 163 (주)타이거오일 신정주유소 서울 양천구 중앙로 226 (신정동) 1519.0 Y SK에너지 양천구 238 다회주유소 서울 은평구 증산로 441 (신사동) 1519.0 Y S-OIL 은평구 164 삼미상사(주)신월IC셀프주유소 서울 양천구 중앙로 331 (신월동) 1524.0 Y SK에너지 양천구 239 타이거주유소 서울 은평구 수색로 188 (증산동) 1524.0 Y SK에너지 은평구 111 이케이에너지(주) 강산제2주유소 서울 성북구 보국문로 52 1525.0 Y 현대오일뱅크 성북구 ... ... ... ... ... ... ... 437 (주)제이제이네트웍스 제이제이주유소 서울 강남구 언주로 716 2348.0 N 현대오일뱅크 강남구 271 필동주유소 서울 중구 퇴계로 196 (필동2가) 2449.0 N GS칼텍스 중구 438 (주)만정에너지 삼보주유소 서울 강남구 봉은사로 433 (삼성동) 2578.0 N GS칼텍스 강남구 237 서계주유소 서울 용산구 청파로 367 (청파동) 2679.0 N GS칼텍스 용산구 272 서남주유소 서울 중구 통일로 30 2684.0 N SK에너지 중구 439 rows × 6 columns
In [151]:import numpy as np gu_data = pd.pivot_table(data=stations, index="구",values="가격", aggfunc=np.mean) gu_data.head()
Out[151]:가격 구 강남구 1890.636364 강동구 1667.571429 강북구 1553.083333 강서구 1606.937500 관악구 1656.142857 In [155]: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
Out[155]:Make this Notebook Trusted to load map: File -> Trust Notebook'EDA' 카테고리의 다른 글
EDA) 인구소멸위기 지역 시각화, 카르토그램 (0) 2023.03.10 EDA) 네이버 API 활용 (0) 2023.03.10 EDA) Selenium 기초 (0) 2023.03.10 EDA) 네이버 영화순위 시각화 (0) 2023.03.10 EDA) 웹크롤링 기초 예제 - 시카고 샌드위치 (0) 2023.03.10