[제로베이스] 유가분석

허재훈·2023년 4월 17일
0

EDA

목록 보기
10/14
post-thumbnail


서울 모든 주유소의 가격 알아보기





  • 이전까지는 어떤 걸 클릭시 사이트 주소가 바뀌었지만,
  • https://www.opinet.co.kr/searRgSelect.do 에서는
  • 지역을 설정하고 조회해도 위 사이트 주소가 변동되지 않음.
  • 그리고 검색어를 넣는게 아닌, 목록 중에 골라서 검색해야됨

목표 데이터

  • 브랜드
  • 가격
  • 셀프 주유 여부
  • 위치


















- 페이지 접근

from selenium import webdriver

# 페이지 접근
driver = webdriver.Chrome("../driver/chromedriver.exe")
driver.get("https://www.opinet.co.kr/searRgSelect.do")
# 메인페이지가 열리고, 팝업창도 하나 뜸
--------------------
# 한번 더 실행하니 원하는 페이지로 이동함
# 1. 한번에 해당 URL로 한번에 접근이 안됨
# 2. 메인 페이지로 접속이 되고, 팝업창이 하나 뜸
driver.get("https://www.opinet.co.kr/searRgSelect.do")
--------------------
main = driver.window_handles
len(main)
# 창 2개 열려있음
>> 2
-----------------------
print(main)
# 창 2개 확인
>>
['AEF1944C39F4CAAF3D942755DE6F1CF5', '3F9DD24164580A9110EBE819ED7CCEE1']
-------------------------
import time

def main_get():

    # 강의대로 하니까 안되어서 구글링해서 처리함
    # 창이 여러개 열리면 0이 메인창이고, 1이 팝업창인 듯

    # 팝업창으로 전환
    driver.switch_to.window(driver.window_handles[1])

    # 팝업창 닫기
    driver.close()
    time.sleep(3) # 셀레니움이 느려서 3초 멈춰준다

    # 메인화면 창으로 전환
    driver.switch_to.window(driver.window_handles[0])

    # 접근 URL 다시 요청
    driver.get("https://www.opinet.co.kr/searRgSelect.do")

main_get()
-------------------------------

- 우리나라 시/도 목록 가져오기

# 지역: 시/도
# 지역관련 html 에 id 가 모두 있다 id = 'SIDO_NM0'
# 우리나라 시/도 목록을 가져오려면, 
# 목록을 포함하고 있는 부모 태그를 가져와서 해당 목록을 가져온다

# id 로 해당 목록을 가져온다
from selenium.webdriver.common.by import By
sido_list_raw = driver.find_element(By.ID, value="SIDO_NM0") # 부모태그
sido_list_raw.text

>>
'            시/도\n            \n             \n              서울\n             \n...
-----------------------------
# html 에서 option 태그를 기준으로 가져온다
# 여러개 가져오므로 find_elements 이다.
sido_list = sido_list_raw.find_elements(By.TAG_NAME, value="option") # 자식태그
len(sido_list)

>> 18
------------------------------
sido_list[1].text
>> '서울'
------------------------------
sido_list[:5].text
# 리스트값 하나하나는 .text 가 되는데, 리스트 몇개는 .text가 안됨
>> 에러
----------------------------------
# 풀네임 가져오기 : value 값 가져오기
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_list_raw.send_keys(sido_names[0])
-------------------------------

- 서울의 구 목록 가져오기

# 서울의 구 목록 가져오기
# 지역: 구
# 지역관련 html 에 id 가 모두 있다 id = 'SIGUNGU_NM0'
# 우리나라 시/도 목록을 가져오려면, 
# 목록을 포함하고 있는 부모 태그를 가져와서 해당 목록을 가져온다

# id 로 해당 목록을 가져온다
gu_list_raw = driver.find_element(By.ID, value="SIGUNGU_NM0") # 부모태그

# html 에서 option 태그를 기준으로 가져온다
# 여러개 가져오므로 find_elements 이다.
gu_list = gu_list_raw.find_elements(By.TAG_NAME, value="option") # 자식태그

gu_names = []

for option in gu_list:
    gu_names.append(option.get_attribute("value"))

# 한줄로 작성
# gu_names = [option.get_attribute("value") for option in gu_list]
gu_names = gu_names[1:]
gu_names[:5], len(gu_names)

>> (['강남구', '강동구', '강북구', '강서구', '관악구'], 25)

- 구까지 선택하기, 엑셀 저장

# 구까지 선택하기
gu_list_raw.send_keys(gu_names[15])
-------------------------
# 엑셀 저장 (사이트 좌측 아래에 엑셀 저장 버튼이 있음)

# driver.find_elements 가져오려는 태그가 여러개인 경우
# driver.find_element 가져오려는 태그가 하나인 경우
# 해당 페이지에서 개발자도구에서 클릭하려는 페이지의 html 값에 우클릭 > copy > copy selector 
# 복사한 값을 아래 value 값에 넣어줌
excel_btn = driver.find_element(By.CSS_SELECTOR, value="#glopopd_excel")
excel_btn.click() # 해당 페이지가 클릭됨

# 2. Xpath 로 엑셀저장
xpath_btn = driver.find_element(By.XPATH, value='//*[@id="glopopd_excel"]')
xpath_btn.click()

# 3. id 로 엑셀저장
id_btn = driver.find_element(By.ID, value='glopopd_excel')
id_btn.click()

- 서울 모든 구 별로 엑셀 다운받기

# 서울 모든 구 별로 엑셀 다운받기

import time
from tqdm import tqdm_notebook

for gu in tqdm_notebook(gu_names):
    element = driver.find_element(By.ID, value="SIGUNGU_NM0") # 부모태그
    element.send_keys(gu)
    time.sleep(3)

    element_get_excel = driver.find_element(By.XPATH, value='//*[@id="glopopd_excel"]')
    element_get_excel.click()
    time.sleep(3)


데이터 정리하기

- 파일 목록 한번에 가져오기 : glob()

  • 파일 목록 한번에 가져오기 : glob()
  • '지역_'으로 시작하고 끝이 xls 로 끝나는 모든 파일을 가져온다.
  • 가져와서 파일의 목록을 저장함
  • glob("../data/지역_*.xls")
import pandas as pd
from glob import glob

# 파일 목록 한번에 가져오기 glob

# '지역_'으로 시작하고 끝이 xls 로 끝나는 모든 파일을 가져온다.
# 가져와서 파일의 목록을 저장함
glob("../data/지역_*.xls")

>>
['../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']

- 파일명 저장 # glob

# 파일명 저장 # glob
stations_files = glob("../data/지역_*.xls")
stations_files[:5]

>>
['../data\\지역_위치별(주유소) (1).xls',
 '../data\\지역_위치별(주유소) (10).xls',
 '../data\\지역_위치별(주유소) (11).xls',
 '../data\\지역_위치별(주유소) (12).xls',
 '../data\\지역_위치별(주유소) (13).xls']
----------------------------------------
# 하나만 읽어보기
tmp = pd.read_excel(stations_files[0])
tmp.tail(2)

# 이름이 이상하다
# 엑셀을 열어보면 2번째 셀까지는 데이터가 없음

tmp = pd.read_excel(stations_files[0], header=2)
tmp.tail(2)

- tmp_raw 에 모두 담기

# tmp_raw 에 모두 담기

tmp_raw = []

for file_name in stations_files:
    tmp = pd.read_excel(file_name, header=2)
    tmp_raw.append(tmp)

tmp_raw

- # 데이터 프레임으로 만들기

# 데이터 프레임으로 만들기
# 형식이 동일하고 연달아 붙이기만 하면 될 때는 concat
station_raw = pd.concat(tmp_raw)
station_raw

# 442 rows × 10 columns 인데,
# 인덱스번호 마지막이 33임

station_raw.info()

>>
<class 'pandas.core.frame.DataFrame'>
Int64Index: 442 entries, 0 to 33
Data columns (total 10 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   지역      442 non-null    object
 1   상호      442 non-null    object
 2   주소      442 non-null    object
 3   상표      442 non-null    object
 4   전화번호    442 non-null    object
 5   셀프여부    442 non-null    object
 6   고급휘발유   442 non-null    object
 7   휘발유     442 non-null    int64 
 8   경유      442 non-null    int64 
 9   실내등유    442 non-null    object
dtypes: int64(2), object(8)
memory usage: 38.0+ KB

----------------------------------
station_raw.columns

>>
Index(['지역', '상호', '주소', '상표', '전화번호', '셀프여부', '고급휘발유', '휘발유', '경유', '실내등유'], dtype='object')

- 컬럼 이름 바꾸고, 일부만 가져오기

# 컬럼 이름 바꾸고, 일부만 가져오기
station = pd.DataFrame({"상호": station_raw["상호"],
                        "주소": station_raw["주소"], 
                        "가격": station_raw["휘발유"], 
                        "셀프": station_raw["셀프여부"], 
                        "상표": station_raw["상표"]
                        })
station.tail()

- 구이름 컬럼 추가하기

# 구이름 컬럼 추가하기
for each in station["주소"]:
    print(each.split())

# 구이름 컬럼 추가하기
for each in station["주소"]:
    print(each.split()[1])

# 구이름 컬럼 추가하기
station["구"] = [each.split()[1] for each in station["주소"]]
station

station["구"].unique(), len(station["구"].unique())

>>
(array(['강동구', '동대문구', '동작구', '마포구', '서대문구', '서초구', '성동구', '성북구', '송파구',
        '양천구', '영등포구', '강북구', '용산구', '은평구', '종로구', '중구', '중랑구', '강서구',
        '관악구', '광진구', '구로구', '금천구', '노원구', '도봉구', '강남구'], dtype=object),
 25)
------------------------
station["가격"]

- 가격 데이터형 변환 object => float

# 가격 데이터형 변환 object => float

station["가격"] = station["가격"].astype('float')

station["가격"]

# 가격 정보가 없는 주유소 : 없네??
station[station["가격"]== "-"]

-----------------------------
station



주유 가격정보 시각화

- # matplolib 한글 대응 작업

# 주유 가격정보 시각화

# matplolib 한글 대응 작업

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":
#     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. sorry ~ ")
# 위 실행하면 에러뜸

# 그래서 아래 실행
import matplotlib.pyplot as plt
# import matplotlib as mpl
from matplotlib import rc

plt.rcParams['axes.unicode_minus'] = False # 마이너스 부호로 인해 한글깨짐현상 방지
rc("font", family='Malgun Gothic')
%matplotlib inline
# 동일 : get_ipython().run_inline_magic("matplotlib", 'inline')

- boxplot(feat. pandas)

# boxplot(feat. pandas)
station.boxplot(column="가격", by="셀프", figsize=(6, 4));

- boxplot(feat. seaborn)

# boxplot(feat. seaborn)
plt.figure(figsize=(6, 4))
sns.boxplot(x="셀프", y="가격", data=station, palette="Set3")
plt.grid(True)
plt.show()

# boxplot(feat. seaborn)
plt.figure(figsize=(8, 6))
sns.boxplot(x="상표", y="가격", hue="셀프", data=station, palette="Set3")
plt.grid(True)
plt.show()

지도 시각화

# 지도 시각화
import json
import folium
import warnings
warnings.simplefilter(action="ignore", category=FutureWarning)

- 가장 비싼 주유소 10곳

# 가장 비싼 주유소 10곳
station.sort_values(by="가격", ascending=False).head(10)

- 가장 저렴한 주유소 10곳

# 가장 저렴한 주유소 10곳
station.sort_values(by="가격", ascending=True).head(10)

- 구별 평균가격

# 구별 평균가격
import numpy as np

gu_data = pd.pivot_table(data=station, 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

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")

위 글은 제로베이스 데이터 취업 스쿨의 강의자료를 참고하여 작성되었습니다.

profile
허재

0개의 댓글

관련 채용 정보