프로젝트명 : 서울시 저렴한 주유소 알아보기
https://www.opinet.co.kr/searRgSelect.do
목표
사이트 구조 확인
브랜드
가격
셀프 주유 여부
위치
from selenium import webdriver
!팝업으로 인해 접근이 되지 않는 경우
driver.switch_to_window(driver.window_handles[-1])
driver.close()
driver.switch_to_window(driver.window_handles[-1])
driver.get()
import time
def main_get():
# 페이지 접근
url = 'https://www.opinet.co.kr/searRgSelect.do'
driver = webdriver.Chrome(executable_path='../driver/chromedriver.exe')
driver.get(url)
# 팝업 전환
driver.switch_to_window(driver.window_handles[-1])
#팝업창 닫기
driver.close()
# 메인 화면 전환
driver.switch_to_window(driver.window_handles[-1])
# 접근 페이지 다시 요청
driver.get(url)
main_get()
url = 'https://www.opinet.co.kr/searRgSelect.do'
driver = webdriver.Chrome(executable_path='../driver/chromedriver.exe')
driver.get(url)
# 지역: 시도
# 부모 태그 먼저 가져오기
sido_list_raw = driver.find_element(By.CSS_SELECTOR, '#SIDO_NM0')
sido_list_raw.text
# select > option 정보가 필요
# TAG_NAME 선택 시 option 정보가 많으니까, find_elements 복수형태로 입력
sido_list = sido_list_raw.find_elements(By.TAG_NAME, 'option')
len(sido_list), sido_list[1].text
# 서울(option) > 서울특별시(option value)
# value 로 fullname을 불러옴
sido_list[1].get_attribute('value')
# 빈리스트 하나 만들어 줌
sido_names =[]
# for()문으로 option 값 들을 가져오고 싶음
# (1)번 방법
# for option in sido_list:
# sido_names.append(option.get_attribute('value'))
# sido_names
#(2)번 방법 ★★한줄 작성
sido_names = [option.get_attribute('value')for option in sido_list]
sido_names
# 맨앞 빈칸 처리
sido_names = sido_names[1:]
sido_names
# 제주도로 넣어주기
# 부모 태그 먼저 가져오기
# sido_list_raw = driver.find_element(By.CSS_SELECTOR, '#SIDO_NM0')
# sido_names = [option.get_attribute('value')for option in sido_list]
# sido_name[16] : '제주특별자치도'
sido_list_raw.send_keys(sido_names[16])
# 부모 태그 먼저 가져오기
gu_list_raw = driver.find_element(By.CSS_SELECTOR, '#SIGUNGU_NM0')
# 자식 태그 가져오기
gu_list = gu_list_raw.find_elements(By.TAG_NAME, 'option')
# for() : 하나씩 정보 가져오기
gu_names = [option.get_attribute('value')for option in gu_list]
gu_names = gu_names[1:] # 맨 앞 공백 1개 빼기 위해
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"]/span').click()
# 시간 소요 오류 방지
import time
# tqdm_notebook을 이용
from tqdm import tqdm_notebook
#for()으로 데이터 수집
for gu in tqdm_notebook(gu_names):
#tqdm_notebook : 얼만큼 진행되는지 눈으로 확인하기 위해 사용
element = driver.find_element(By.CSS_SELECTOR, '#SIGUNGU_NM0')
# 부모 태그
element.send_keys(gu)
# 키 값(모든 구들)을 하나씩 보내 줌
time.sleep(3)
# 한번 걸어 줌
element_get_excel = driver.find_element(By.CSS_SELECTOR, '#glopopd_excel').click()
# 엑셀 저장
time.sleep(3)
# 한번 걸어 줌
# glob
# 파일의 목록을 읽어 오고 정리해 줌
import pandas as pd
from glob import glob
glob('../data/지역_*.xls')
stations_files = glob('../data/지역_*.xls')
stations_files[:5]
# test : 하나만 읽어와 보기
tmp = pd.read_excel(stations_files[0])
tmp.tail(2)
# 엑셀 파일을 열어보면 1~2줄은 데이터가 없어서 위와 같이 출력 됨
# 예쁘게 출력하기 위해 아래와 같은 코드를 써야 함
# 2번째 이후 부터 컬럼을 가져와라..!
tmp = pd.read_excel(stations_files[0], header=2)
tmp.tail(2)
# stations_files = glob('../data/지역_*.xls') : 모든 엑셀 취합 명령
# tmp = pd.read_excel(stations_files[0], header=2) : 엑셀 읽어오기 명령
tmp_raw = []
for file_name in stations_files:
tmp = pd.read_excel(file_name, header=2)
tmp_raw.append(tmp)
tmp_raw
# 위 자료를 데이터 프레임 형식으로 변환
station_raw = pd.concat(tmp_raw)
station_raw
station_raw.info()
# 어떤 컬럼들이 있는지 확인
station_raw.columns
stations = pd.DataFrame({
'상호' : station_raw['상호'],
'주소' : station_raw['주소'],
'가격' : station_raw['휘발유'],
'셀프' : station_raw['셀프여부'],
'상표' : station_raw['상표']
})
stations.tail()
for eachAddress in stations['주소']:
print(eachAddress.split()[0])
stations['구'] = [eachAddress.split()[1] for eachAddress in stations['주소']]
# 구, 컬럼 = [eachDDRESS 를 잘라서 1번째만 가져온다, station['주소']에서 하나씩 뽑아서]
stations
stations['구'].unique(), len(stations['구'].unique())
stations['가격'] = stations['가격'].astype('float')
stations[stations['가격'] == '-']
stations = stations[stations['가격'] != '-']
stations.tail()
stations['가격'] = stations['가격'].astype('float')
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"
rc("font", family="Malgun Gothic")
# 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("Unkown system. sorry~~")
stations.boxplot(column='가격', by='셀프', figsize=(8,8))
plt.figure(figsize=(8,8))
sns.boxplot(x='셀프', y='가격', data=stations, palette='Set3')
plt.grid(True)
plt.show()
# 구분기준 : hue='셀프'
plt.figure(figsize=(8,8))
sns.boxplot(x='상표', y='가격', hue='셀프',data=stations, palette='Set1')
plt.grid(True)
plt.show()
import json
import folium
#경고 문구가 뜨는게 싫어서 설정.
import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)
# 가격 표현방식 = 평균값 : aggfunc=np.mean
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='cartodb positron',
)
# Choropleth :경계선 좌표값 표시하기
folium.Choropleth(
geo_data=geo_str, # 우리나라 경계선 좌표값이 담긴 데이터
data=gu_data,
columns=[gu_data.index, "가격"],
key_on="feature.id",
fill_color="PuRd",
).add_to(my_map)
my_map