본문 바로가기
제로베이스 데이터 스쿨/일일 스터디 노트

26일차 스터디노트 / 파이썬 웹데이터 수집, 파이썬 Selenium, 주유 가격 정보 시각화, boxplot, folium

by 김뎀뎀 2023. 2. 7.

※제로베이스 데이터 취업스쿨 11기 수강 중

📗 26일차 공부 내용 요약

 

파이썬에서 웹데이터를 수집하기 위해, 셀레니움에 대해 알아보고, 유가 데이터를 수집하고 시각화해보았다

 

1. 셀레니움(Selenium) : 셀레니움의 필요성을 알아보고, 기초적인 동작들을 알아보았다.

2. 한국석유공사 Opinet 데이터 수집 : 셀레니움을 통해 유가 데이터를 수집해보았다

3. 주유 가격 데이터 정리수집한 다수의 엑셀 파일을 불러오고, 데이터프레임으로 변환해보았다

4. 주유 가격 정보 시각화 : boxplot과 지도 시각화를 진행해보았다.

 


📖  26일차 공부 내용 자세히

 

1. 셀레니움(Selenium)

 

■ selenium webdriver 사용하기

#selenium 패키지에서 webdriver 기능을 가져온다
from selenium import webdriver 

#whbdriver 중 chrome driver를 활용한다, cromedriver의 경로를 옵션으로 넣어준다
driver = webdriver.Chrome(executable_path='../driver/chromedriver.exe') 

#이제 driver 변수를 이용해서 chrome을 제어할 수 있다
#get 명령으로 접근하고 싶은 주소를 지정한다
driver.get("https://naver.com")

#실행창 닫기
driver.quit()

 

■ 기본동작

from selenium import webdriver 
#from selenium.webdriver.common.by import By

driver = webdriver.Chrome(executable_path='../driver/chromedriver.exe') 
driver.get("https://pinkwink.kr")

# 화면 최대 크기 설정
driver.maximize_window()

# 화면 최소 크기 설정
driver.minimize_window()

# 화면 크기 설정
driver.set_window_size(600,600)

# 새로 고침
driver.refresh()

# 뒤로 가기
driver. back()

# 앞으로 가기
driver.forward()

# 클릭
from selenium.webdriver.common.by import By

first_content = driver.find_element(By.CSS_SELECTOR, '#content > div.cover-masonry > div > ul > li:nth-child(1)')
first_content.click()

# 새로운 탭 생성하기
driver.execute_script('window.open("https://www.pinkwink.kr")')

# 탭 이동
driver.switch_to.window(driver.window_handles[1])

#탭 닫기
driver.close()

 

■ 화면 스크롤

  • ActionChains
    • 마우스 이동, 마우스 버튼 동작, 마우스 끌어서 놓기 등 좀 더 복잡한 작업을 수행할 때 유용
    • 특정 영역까지 스크롤 이동, 동적 페이지 구동 등
    • from selenium.webdriver import ActionChains
# <1. 스크롤 가능한 높이(길이)>
driver.execute_script('return document.body.scrollHeight')
#5658
#현재 내가 보고 있는 document의 body 부분에서 scrollHight의 값을 반환해라


# <2. 화면 스크롤 하단 이동>
driver.execute_script('window.scrollTo(0, document.body.scrollHeight);')


# <3. 화면 스크롤 상단 이동>
driver.execute_script('window.scrollTo(0,0)')


# <4. 현재 보이는 화면 스크린샷 저장>
driver.save_screenshot('./last_height.png')


# <5. 특정 태그 지정까지 스크롤 이동>
from selenium.webdriver import ActionChains

# <6. 원하는 지점의 태그값 변수에 담기>
some_tag = driver.find_element(By.CSS_SELECTOR, "#content > div.cover-list > div > ul > li:nth-child(3)")

  #ActionChains 객체에 현재 사용하는 driver를 옵션으로 넣어 변수에 담기
action = ActionChains(driver)

  #ActionChains가 제공하는 기능 move_to_element로 some_tag 위치에 perform() 실행해 이동
action.move_to_element(some_tag).perform()

 

■ 검색어 입력

  •  send_keys()
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome('../driver/chromedriver.exe')
driver.get('https:/pinkwink.kr')

# < 1.돋보기 버튼 선택 >
from selenium.webdriver import ActionChains

search_tag = driver.find_element(By.CSS_SELECTOR, '.search')
action = ActionChains(driver)
action.click(search_tag)
action.perform()

# < 2.검색어 입력 >
driver.find_element(By.CSS_SELECTOR, '#header > div.search.on > input[type=text]').send_keys('딥러닝')

# < 3.검색 버튼 클릭 >
driver.find_element(By.CSS_SELECTOR,'#header > div.search.on > button').click()

 

■ selenium과 beautifulsoup 함께 사용하기

#현재 화면 html 코드 가져오기
from selenium import webdriver
from bs4 import BeautifulSoup

driver = webdriver.Chrome('../driver/chromedriver.exe')
driver.get('https:/pinkwink.kr')
driver.page_source

req = driver.page_source
soup = BeautifulSoup(req, 'html.parser')

soup.select('.post-item')

 

2. 한국석유공사 Opinet > 싼주유소찾기 데이터 수집

 

■ 페이지 열기

url = "https://www.opinet.co.kr/searRgSelect.do"
driver = webdriver.Chrome("../driver/chromedriver.exe")
driver.get(url)
driver.get(url)

 

■ 서울시 선택

from selenium.webdriver.common.by import By

sido_list_raw = driver.find_element(By.ID, "SIDO_NM0")
sido_list = sido_list_raw.find_elements(By.TAG_NAME, "option")
sido_names = [ option.get_attribute("value") for option in sido_list ]

#서울시 선택하기
sido_list_raw.send_keys(sido_names[0])

 

■ 서울시 모든 구 정보 엑셀 저장

import time
from tqdm import tqdm_notebook

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 ]

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)

 

 

3. 주유 가격 데이터 정리

 

■ 다수의 엑셀 파일 한 번에 가져오기 

  • glob()
import pandas as pd
from glob import glob

#파일 불러오기
glob("../data/지역_*.xls")

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

#하나만 읽어보기
tmp = pd.read_excel(stations_files[0], header = 2) 
#엑셀 파일의 1,2행의 내용이 없기 때문에 2번째 행 이후부터 불러옴

#모든 엑셀 파일 불러와서 리스트로 만들기
tmp_raw = []

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

 

■ 데이터 합쳐서 데이터 프레임 만들기

  • concat()
    • 형식이 동일하고 연달아 붙이기만 하면 될 때
    • 행으로 밑에 추가하는 식으로 붙음
#데이터 합치기
station_raw = pd.concat(tmp_raw)

#데이터프레임 만들기
stations = pd.DataFrame({
    "상호": station_raw["상호"],
    "주소": station_raw["주소"],
    "가격": station_raw["휘발유"],
    "셀프": station_raw["셀프여부"],
    "상표": station_raw["상표"]
})
stations.tail()

 

■ 데이터 프레임 세부 편집

# '구'컬럼 추가
stations["구"] = [eachAddress.split()[1] for eachAddress in stations["주소"]]

# 가격 데이터 형 변환
stations["가격"] = stations["가격"].astype("float")

#인덱스 재정렬
stations.reset_index(inplace=True)

#기존 인덱스 삭제
del stations["index"]

 

4. 주유 가격 정보 시각화

 

■ 주유소 브랜드별 가격 boxplot

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

 

■ 구별 가격 지도 시각화

#구별 가격 피봇테이블
import numpy as np

gu_data = pd.pivot_table(data=stations, index = "구", values = "가격", aggfunc=np.mean)

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

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


➰ 26일차 후기

내가 작성하는 코드대로 사이트가 작동하는 것이 신기했다.

구현만 해보았던, boxplot이 의미하는 바를 알게 되는 것도 좋았다.

처음에는 plot 하나 그리는 것도  낯설어 했는데, 계속하다보니 익숙해지고 있다.

그래도 아직 완전히 손에 익은 것은 아니라, 앞 부분 내용 복습을 필히 해야겠다.


※본 내용은 제로베이스 데이터 취업 스쿨에서 제공하는 학습 내용에 기반합니다.