"셀프 주유소가 정말 저렴하나요?"에 대한 답변을 하기 위해 예제를 해결해보자.
- https://www.opinet.co.kr/searRgSelect.do
- 사이트 구조 확인
- 목표 데이터
- 브랜드
- 가격
- 셀프 주유 여부
- 위치
앞선 영화 예제에서는 원하는 데이터가 필요한 공간의 url 주소가 변경되었다.
하지만 오늘 할 예제는 url 주소가 바뀌지 않아 해당 주소값에 원하는 데이터가 없을 확률이 높다. 따라서 직접 버튼을 눌러 원하는 데이터에 접근해야한다. -> selenium 사용
방법 1: 오른쪽 상단 점 세개 -> 도구 더보기 -> 개발자 도구
방법 2: 오른쪽 마우스 클릭 -> 검사
방법 3: Ctrl + Shift + i
클릭해야할 데이터의 태그들을 확인해보자.
지역에 시/도, 시/군/구, 읍/면/동의 태그를 확인해봤을때 id값으로 되어있음을 확인 할 수 있다. 따라서 id는 1개만 존재하기 때문에 접근하기가 쉽다.
원하는 도/시/군을 이동해 엑셀 저장을 누르면 원하는 데이터의 엑셀 파일이 저장된다.
from selenium import webdriver
url = "https://www.opinet.co.kr/searRgSelect.do"
driver = webdriver.Chrome("../driver/chromedriver.exe")
driver.get(url)
기대했던 페이지와 다르게 메인 화면이 나오고 팝업창까지 나온다.
driver.get(url)
한번 더 입력하면 원하는 페이지가 나온다.
- 문제점
- 해당 URL로 한 번에 접근이 안된다.
- 메인페이지로 접속이 되고, 팝업창이 하나 나온다.
import time
from selenium.webdriver.common.by import By
# 페이지 접근
url = "https://www.opinet.co.kr/searRgSelect.do"
driver = webdriver.Chrome("../driver/chromedriver.exe")
driver.get(url)
time.sleep(3)
# 팝업창 화면 전환
driver.switch_to_window(driver.window_handles[-1])
# 팝업창 닫아주기
driver.close()
# 메인화면 창으로 전환
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), sido_list[1].text
sido_list[1].get_attribute("value")
sido_names = [option.get_attribute("value") for option in sido_list]
sido_names = sido_names[1:]
sido_names
sido_list_raw.send_keys(sido_names[16])
# 시/군/구
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:]
gu_names[:5], len(gu_names)
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()
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)
importort pandas as pd
from glob import glob
# !pip install glob
# 파일 목록 한 번에 가져오기
glob("../data/지역_*.xls")
stations_files = glob("../data/지역_*.xls")
stations_files[:5]
tmp = pd.read_excel(stations_files[0])
tmp.tail(2)
엑셀파일에 1,2번째 행에는 내용이 없기 때문에 header=2 해줘야 컬럼 이름이 제대로 들어간다.
tmp = pd.read_excel(stations_files[0], 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)
![](https://velog.velcdn.com/images/zer0/post/194659c6-b1f4-4be0-ae72-f71c8a9803cd/image.png
stations_raw = pd.concat(tmp_raw)
stations_raw
stations = pd.DataFrame({
"상호": stations_raw["상호"],
"주소": stations_raw["주소"],
"가격": stations_raw["휘발유"],
"셀프": stations_raw["셀프여부"],
"상표": stations_raw["상표"],
})
stations
for eachAddress in stations["주소"]:
print(eachAddress.split()[1])
stations["구"] = [eachAddress.split()[1] for eachAddress in stations["주소"]]
강의 상 휘발유 가격이 object로 되어있었는데 실제 데이터에서는 int로 되어있어서 바로 변환 가능했다.
stations["가격"] = stations["가격"].astype("float")
stations
# 가격 정보가 있는 주유소만 사용
stations = stations[stations["가격"] != "-"]
stations.reset_index(inplace=True)
stations.tail()
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")
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~")
# boxplot(feat. pandas)
stations.boxplot(column='가격', by="셀프", figsize=(12, 8))
# boxlot(feat. seaborn)
plt.figure(figsize=(12, 8))
sns.boxplot(x="셀프", y="가격", data=stations, palette="Set3")
plt.grid(True)
plt.show()
palette 설정을 해줘서 색상이 들어갔다.
# boxlot(feat. seaborn)
plt.figure(figsize=(12, 8))
sns.boxplot(x="상표", y="가격", hue="셀프", data=stations, palette="Set3") # hue 구분 기준
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()
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",
)
my_map
"이 글은 제로베이스 데이터 취업 스쿨 강의를 듣고 작성한 내용으로 제로베이스 데이터 취업 스쿨 강의 자료 일부를 발췌한 내용이 포함되어 있습니다."