4.5 Selenium 기초2_데이터 수집

소리·2023년 10월 10일
0

(질문) 셀프 주유소가 정말 저렴한가?

(1) 셀레니움으로 웹페이지 접근

from selenium import webdriver

#페이지 접근
url = "https://www.opinet.co.kr/searRgSelect.do"
driver = webdriver.Chrome("../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)

(1-1) 함수로 전환해서 한 번에 불러올 수 있게 만들 수 있다.

+타임 모듈로 시간을 잠깐 뭠춰서 셀레니움이 작동할 수 있는 시간을 확보한다.

import time 

def main_get():
    # 페이지 접근 
    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()
   
   time.sleep(3)
   
   # 메인화면 창으로 전환 
    driver.switch_to_window(driver.window_handles[-1])
  
  # 접근 URL 다시 요청 
    driver.get(url)
   
main_get() #지정한 함수로 불러오기

(2) 가져오고자 하는 정보, 위치 찾기 (시/도)

#id가 SIDO_NM0 인 요소를 찾고 문자를 뽑아내기
sido_list_raw = driver.find_element_by_id("SIDO_NM0")
sido_list_raw.text


#태그 이름이 option인 것을 뽑아내기
sido_list = sido_list_raw.find_elements_by_tag_name("option")

len(sido_list), sido_list[17].text
sido_list[1].get_attribute("value") #1번째 value 속성값을 얻기 (하나 꺼내보기)



#속성값에 담긴 텍스트 모두 뽑기 방법1
sido_names = [] 

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[:5]

sido_names = sido_names[1:]
sido_names

sido_list_raw.send_keys(sido_names[0]) #화면에 값 보내기

(3) (2) 가져오고자 하는 정보, 위치 찾기 (구)

#위와 동일 불러오는 대상만 다름
u_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)

gu_list_raw.send_keys(gu_names[15])

(4) 엑셀 저장

driver.find_element_by_css_selector("#glopopd_excel").click() #엑셀 저장을 클릭하는 곳의 셀렉터 위치가 저것이다.

#동일한 방법 다른 경로 : xpath 이용하기
driver.find_element_by_xpath('//*[@id="glopopd_excel"]').click()

#동일한 방법 다른 경로 : id 이용하기
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_id("glopopd_excel").click()
    time.sleep(3) 

driver.close() 

(5) 데이터 정리

import pandas as pd 
from glob import glob 

stations_files = glob("../data/지역_*.xls") # 목록 한번에 가져오기

#여러 파일을 가져왔는데 그 중 파일 하나를 읽기
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)
    
#형식이 동일하고 연달아 붙이면 될 때 concat
stations_raw = pd.concat(tmp_raw)


stations = pd.DataFrame({
    "상호": stations_raw["상호"],
    "주소": stations_raw["주소"], 
    "가격": stations_raw["휘발유"],
    "셀프": stations_raw["셀프여부"],
    "상표": stations_raw["상표"]
})

stations["구"] = [eachAddress.split()[1] for eachAddress in stations["주소"]]

# stations[stations["구"] == "서울특별시"]
# stations.loc[stations["구"] == "서울특별시", "구"] = "성동구"
# stations[stations["구"] == "특별시"]
# stations.loc[stations["구"] == "특별시", "구"] = "도봉구"

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

# 가격 정보가 있는 주유소만 사용 
stations = stations[stations["가격"] != "-"]
stations["가격"] = stations["가격"].astype("float")

# 인덱스 재정렬 
stations.reset_index(inplace=True)
del stations["index"

(6) 주유 가격 정보 boxplot 시각화

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("Unkown system. sorry~~")
    
    
    
# boxplot(feat. pandas)
stations.boxplot(column="가격", by="셀프", figsize=(12, 8));


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

(7) 지도 시각화

import json 
import folium
import warnings
warnings.simplefilter(action="ignore", category=FutureWarning)


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.choropleth(
    geo_data=geo_str,
    data=gu_data,
    columns=[gu_data.index, "가격"],
    key_on="feature.id",
    fill_color="PuRd"
)
my_map
profile
데이터로 경로를 탐색합니다.

0개의 댓글