[01/31] Selenium 유가 분석

이아연·2024년 2월 1일
0

유가 분석 (feat.Selenium)

  • 셀레니움 기본 동작
  • 검색어 입력
  • Selenium + BeauifulSoup
  • 데이터 확보하기 위한 작업(구별 엑셀파일 저장)
  • 데이터 정리하기(엑셀파일 정리)
  • 주유 가격 정보 시각화

Requirements

1. 셀레니움 설치

from selenium import webdriver
#from selenium.webdriver.common.by import By
driver = webdriver.Chrome('../driver/chromedriver.exe')
driver.get('https://pinkwink.kr')
  • 창 닫기
driver.quit()

셀레니움 기본 동작

  • 화면 최대 크기 설정
driver.maximize_window()
  • 화면 최소 크기 설정
driver.minimize_window()
  • 화면 크기 설정
driver.set_window_size(1000, 800)
  • 새로 고침
driver.refresh()
  • 뒤로가기
driver.back()
  • 앞으로 가기
driver.forward()
  • 화면 최소 크기 설정
driver.maximize_window()
  • 클릭
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.naver.com")')
  • 탭 이동
    driver.window_handles[0] : 탭에 인덱스 지정
driver.switch_to.window(driver.window_handles[0])
  • 탭 닫기 - 열려있는 탭 하나씩 하나씩 닫음
driver.close()
  • 전체 탭 닫기 - 작업 끝났으면 웬만하면 quit사용
driver.quit()
  • 스크롤 가능한 높이(길이)
  • 자바스크립트 코드 실행
driver.execute_script('return document.body.scrollHeight') # body에서 스크롤 할 수 있는 높이 반환
  • 화면 스크롤 하단 이동
driver.execute_script('window.scrollTo(0, document.body.scrollHeight);')
  • 화면 스크롤 상단 이동
driver.execute_script('window.scrollTo(0, 0);')
  • 현재 보이는 화면 스크린샷 저장
driver.save_screenshot('./last_height.png')
  • 특정 태그 지점까지 스크롤
    ActionChains
from selenium.webdriver import ActionChains
some_tag = driver.find_element(By.CSS_SELECTOR,'#content > div.cover-list > div > ul > li:nth-child(1)')
action = ActionChains(driver)
action.move_to_element(some_tag).perform()

검색어 입력

  • CSS_SELECTOR

Requirements

from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome('../driver/chromedriver.exe')
driver.get('https://naver.com')

검색어 입력하기
keyword.clear() 기존 키워드 없애고 검색

keyword = driver.find_element(By.CSS_SELECTOR,'#query')
keyword.clear()
keyword.send_keys('파이썬')

검색 버튼 클릭하기

search_btn=driver.find_element(By.CSS_SELECTOR,'#sform > fieldset > button')
search_btn.click()
  • XPATH
    Memo
'//':최상위 
'*':자손 태그
'/': 자식 태그
'//*[@id="main_pack"]/section[2]/div/ul/li[1]/div/div[2]/div[2]/a'

검색어 입력하기

driver.find_element(By.XPATH, '//*[@id="query"]').send_keys('xpath')

클릭하기

driver.find_element(By.XPATH, '//*[@id="sform"]/fieldset/button' ).click()

<핑크 윙크에서 검색하기>

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

1. 돋보기 버튼 선택
Actionchains이용

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 > input[type=text]').send_keys('딥러닝')

3. 검색 버튼 클릭

driver.find_element(By.CSS_SELECTOR, '#header > div.search.on > button').click()

Selenium + BeauifulSoup

현재 화면의 html 코드 가져오기

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

데이터 확보하기 위한 작업(구별 엑셀파일 저장)

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

지역 : 시/도 부모 태그를 가져와서 그 아래 있는 태그를 불러오기

sido_list_raw=driver.find_element(By.ID, 'SIDO_NM0')
sido_list_raw.text

여러 개일 때는 elements

sido_list = sido_list_raw.find_elements(By.TAG_NAME, 'option')
len(sido_list), sido_list[17].text

result : (18, '제주')

<\option value> 안의 속성 값을 가져옴

sido_list[1].get_attribute('value')

result : '서울특별시'

#1. for문 이용

sido_names =[]
for option in sido_list:
    sido_names.append(option.get_attribute('value'))
sido_names

#2. for문 - list comprehension

#2. for- list comprehension
sido_names=[option.get_attribute('value') for option in sido_list]
sido_names[:5]

시/도 검색

sido_list_raw.send_keys(sido_names[0])

구 리스트

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.ID,'glopopd_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)

데이터 정리하기(엑셀파일 정리)

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)
tmp.head(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)
station_raw


상호, 주소, 가격, 셀프, 상표를 컬럼으로 설정하여 DataFrame 만들기

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

'주소'컬럼에서 split()하여 '구'컬럼 추가

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

가격 정보 있는 주유소만 사용

stations = stations[stations['가격'] != '-']
stations.tail()


가격 정보를 float형식으로 바꾸기

stations['가격'] = stations['가격'].astype('float')

인덱스 재정렬

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')
# %matplotlib inline
plt.rcParams['axes.unicode_minus']=False
rc('font',family='Malgun Gothic')

셀프 주유 여부에 따른 가격 차이
boxplot(feat.pandas)

stations.boxplot(column='가격', by='셀프', figsize=(12, 8))


mid값,
박스 범위 = mid값 기준 25%위/아래 -> 총합 50%의 값
outlier = box범위의 1.5배 초과한 case, outlier는 따로 표시

#boxplot(feat.seaborn)

plt.figure(figsize=(12, 8))
sns.boxplot(x='셀프', y='가격', data=stations, palette='Set2')
plt.grid(True)
plt.show()

상표별 셀프 주유 여부에 따른 가격 차이

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

지도 시각화

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='CartoDB Positron')
folium.Choropleth(
    geo_data=geo_str,
    data=gu_data,
    columns=[gu_data.index, '가격'],
    key_on='feature.id',
    fill_color='PuRd',
    popup=folium.Popup()
).add_to(my_map)
my_map 

자료출처 : 제로베이스 데이터 취업 스쿨

profile
Hi Welcome

0개의 댓글