본문 바로가기

데이터 사이언스 공부/파이썬으로데이터주무르기

self gas station analysis

# 선요약

1. selenium으로 구글 드라이브에서 웹크롤링을 할 수 있다.

2. driver의 find_element_by_xpath로 element에 접근할 수 있다.

3. concat으로 두 dataframe를 병합할 수 있다. reset_index로 인덱스를 재설정할 수 있다.

 

 

selenium 이용해서 웹크롤링 예제

 

from selenium import webdriver
import time

driver = webdriver.Chrome('driver/chromedriver')
driver.get('https://www.naver.com/')
time.sleep(1)
#click login page btn
xpath = """//*[@id="account"]/div/a/i"""
driver.find_element_by_xpath(xpath).click()
time.sleep(1)
#input id and pw
usr_id = "---"
usr_pw = "---"
driver.execute_script("document.getElementsByName('id')[0].value=\'" + usr_id + "\'")
time.sleep(1)
driver.execute_script("document.getElementsByName('pw')[0].value=\'" + usr_pw + "\'")
time.sleep(1)
#click login btn
xpath = """//*[@id="log.login"]"""
driver.find_element_by_xpath(xpath).click()
time.sleep(1)
#get mail html
from bs4 import BeautifulSoup
driver.get("https://mail.naver.com")
time.sleep(1)
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
temp = soup.find('div', 'name _ccr(lst.from) ')
rList = soup.find_all('div', 'name _ccr(lst.from) ')
sList = [rList[n].find('a').get_text() for n in range(0, len(rList))]
print(temp)

 

데이터 가져오기

 

from selenium import webdriver
import time
#드라이버열기
driver = webdriver.Chrome('driver/chromedriver')
driver.get('http://www.opinet.co.kr/user/main/mainView.do')
time.sleep(1)
#링크클릭
xpath = """//*[@id="quick_ul"]/li[2]/a/span"""
driver.find_elements_by_xpath(xpath).click()
time.sleep(1)
#구 리스트 가져오기
xpath = """//*[@id="SIGUNGU_NM0"]"""
gu_list_raw = driver.find_element_by_xpath(xpath)
gu_list = gu_list_raw.find_elements_by_tag_name("option")
gu_names = [option.get_attribute("value") for option in gu_list]
gu_names.remove('')
#구 리스트의 각 구 이름을 값으로 전달하고 그 구에 해당하는 엑셀 파일 저장
from tqdm import tqdm
for gu in tqdm(gu_names):
    element = driver.find_element_by_id("SIGUNGU_NM0")
    element.send_keys(gu)
    time.sleep(2)
    
    xpath = """//*[@id="searRgSelect"]/span"""
    driver.find_element_by_xpath(xpath).click()
    time.sleep(1)

    xpath = """//*[@id="glopopd_excel"]/span"""
    driver.find_element_by_xpath(xpath).click()
    time.sleep(1)

driver.close()

 

df 만들기

 

import pandas as pd
from glob import glob

stations_files = glob('data/지역*.xls')
tmp_raw = []
#파일읽어서 리스트에 추가
for file_name in stations_files:
    tmp = pd.read_excel(file_name, header = 2)
    tmp_raw.append(tmp)
#열방향으로 합치기
station_raw = pd.concat(tmp_raw)
#이름바꿔서 데이터프레임 바꾸기
stations = pd.DataFrame({'주유소':station_raw['상호'],'주소':station_raw['주소'],'가격':station_raw['휘발유'],'셀프':station_raw['셀프여부'],'상표':station_raw['상표']})
#구 칼럼 추가하기
stations['구'] = [eachAddress.split()[1] for eachAddress in stations['주소']]
#구 이름 제대로 들어왔는지 확인하기
print(stations['구'].unique())
#가격에 - 들어간 로우 삭제
stations = stations[stations['가격']!='-']
#float data type로 변경
stations['가격'] = [float(value) for value in stations['가격']]
#인덱스 처음부터 다시 설정하기
stations.reset_index(inplace=True)
del stations['index']
print(stations['가격'].unique())
stations.to_csv('./data/self_gas_station.csv', sep=',', encoding='utf-8')

 

결과 그리기

 

import pandas as pd
#csv파일 읽기
stations = pd.read_csv('./data/self_gas_station.csv',encoding='utf-8',index_col=0)
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
import seaborn as sns
#한글읽기
plt.rcParams['axes.unicode_minus']=False
rc('font',family='AppleGothic')
#draw boxplot
plt.figure(figsize=(12,8))
sns.boxplot(x="상표", y="가격", hue="셀프", data=stations, palette="Set3")
plt.show()

plt.figure(figsize=(12,8))
sns.boxplot(x="상표", y="가격", data=stations, palette="Set3")
sns.swarmplot(x="상표", y="가격", data=stations, color=".6")
plt.show()

 

map에 표시

 

import numpy as np
import pandas as pd
import json
import folium
import googlemaps
import warnings
warnings.simplefilter(action="ignore", category=FutureWarning)

#csv파일 읽기
stations = pd.read_csv('./data/self_gas_station.csv',encoding='utf-8',index_col=0)
#pivot table를 이용해서 구별 가격 정보로 변경하고 가격은 평균값으로 정리
gu_data = pd.pivot_table(stations, index=["구"], values=["가격"], aggfunc=np.mean)
#json 읽어서 지도 그리기
geo_path = './data/seoul_geo_simple.json'
geo_data = json.load(open(geo_path, encoding='utf-8'))
#folium으로 map 객체 생성
map = folium.Map(location=[37.5502, 126.982], zoom_start=10.5, titles='Stamen Toner')
map.choropleth(geo_data = geo_data,
               data = gu_data,
               columns = [gu_data.index, '가격'],
               fill_color = 'PuRd', #puRd, YlGnBu
               key_on = 'feature.id')
map.save('./data/map_gas.html')

 

import numpy as np
import pandas as pd
import json
import folium
import googlemaps
import warnings
from tqdm import tqdm
warnings.simplefilter(action="ignore", category=FutureWarning)

#csv파일 읽기
stations = pd.read_csv('./data/self_gas_station.csv',encoding='utf-8',index_col=0)
price_top10 = stations.sort_values(by='가격', ascending=False).head(10)
price_btm10 = stations.sort_values(by='가격', ascending=True).head(10)

gmaps_key = "AIzaSyA_Fh_UX0YoUhUtm4Lx-CiZ5S7VdBVhOEo"
gmaps = googlemaps.Client(key=gmaps_key)
#상위10개 주유소 위도와 경도 데이터 얻기
lat=[]
lng=[]
for n in tqdm(price_top10.index):
    try:
        tmp_add = str(price_top10['주소'][n]).split('(')[0]
        tmp_map = gmaps.geocode(tmp_add)
        tmp_loc = tmp_map[0].get('geometry')
        lat.append(tmp_loc['location']['lat'])
        lng.append(tmp_loc['location']['lng'])
    except:
        lat.append(np.nan)
        lng.append(np.nan)
price_top10['lat']=lat
price_top10['lng']=lng
#하위10개 주유소 위도와 경도 데이터 얻기
lat=[]
lng=[]
for n in tqdm(price_btm10.index):
    try:
        tmp_add = str(price_btm10['주소'][n]).split('(')[0]
        tmp_map = gmaps.geocode(tmp_add)
        tmp_loc = tmp_map[0].get('geometry')
        lat.append(tmp_loc['location']['lat'])
        lng.append(tmp_loc['location']['lng'])
    except:
        lat.append(np.nan)
        lng.append(np.nan)
price_btm10['lat']=lat
price_btm10['lng']=lng
#얻은 위도, 경도를 맵에 추가
map = folium.Map(location=[37.5202, 126.975], zoom_start=10.5)
for n in price_top10.index:
    if pd.notnull(price_top10['lat'][n]):
        folium.CircleMarker([price_top10['lat'][n], price_top10['lng'][n]], radius=15, color='#CD3181', fill_color='#CD3181').add_to(map)
for n in price_btm10.index:
    if pd.notnull(price_btm10['lat'][n]):
        folium.CircleMarker([price_btm10['lat'][n], price_btm10['lng'][n]], radius=15, color='#3186cc', fill_color='#3186cc').add_to(map)
map.save('./data/map_gas_gas.html')

 

'데이터 사이언스 공부 > 파이썬으로데이터주무르기' 카테고리의 다른 글

time series  (0) 2020.05.12
chicago analysis  (0) 2020.05.12
crime analysis  (0) 2020.05.12
cctv analysis  (0) 2020.05.12