Web Data 02 selenium

yoong·2023년 5월 19일

6.EDA

목록 보기
7/8

01. Selenium

Selenium 기초

01. 사용이유

Beautiful Soup 만으로 해결할 수 없을 때,

  • 접근할 웹 주소를 알수 없을때,
  • 자바스크립트를 사용하는 웹페이지경우
  • 웹 브라우저로 접근하지 않으면 안될 때,

02. 정의

  • 웹브라우저를 원격 조작하는 도구
  • 자동으로 url열고 클릭등이 가능
  • 스크롤,문자 입력,화면 캡쳐등

03. 설치

1) 주피터 노트북에 셀레니움 설치
for window/intel mac

conda install selenium 

for arm m1

pip install selenium

2) chromedriver 설치
a. 구글 세팅에서 구글 버전확인후 구글링해서 버전에 맞는 크롬드라이버 설치하기
b. 주피터노트북에서 불러오기

!pip list | grep sele
from selenium import webdriver

[참고]DeprecationWarning: executable_path has been deprecated 해결하기
:https://velog.io/@sangyeon217/deprecation-warning-executablepath-has-been-deprecated

04. 문법

1) 변경사항

#변경전
find_element_by_id('id')
find_element_by_xpath('xpath')
find_element_by_css_selector('css selector')
#변경후
find_element(By.ID, "id")
find_element(By.XPATH, "xpath")
find_element(By.CSS_SELECTOR, "css selector")

2) 주요 문법 기능
a. 화면크기,기본 기능

from selenium import webdriver

driver = webdriver.Chrome(executable_path='../driver/chromedriver')
driver.get("http://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.naver.com")')

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

# 탭 닫기1 - 탭하나씩닫기 
driver.close()

# 탭 닫기2 - 전체종료
driver.quit()

b. 화면스크롤

#스크롤 가능한 높이(길이) #자바스크립트 코드 실행 #body스크립트 반환 
driver.execute_script('return document.body.scrollHeight')


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


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


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


# 특정 태그 지점까지 스크롤 이동
#hover : 이미지 살짝 커지는 효과(ActionChains로 구현가능)
from selenium.webdriver import ActionChains

some_tag = driver.find_element(By.CSS_SELECTOR,'#content > div.cover-thumbnail-list > div > ul > li:nth-child(1)')
action = ActionChains(driver)
action.move_to_element(some_tag).perform()

c. 검색어 입력

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

driver = webdriver.Chrome('../driver/chromedriver')
driver.get('https://www.naver.com')


# 방법1: CSS_SELECOR로 찾는 방법 
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()

# 방법2: X_PATH
# '//': 최상위 루트(경로)
# '*': 자손 태그
# '/': 자식 태그 
# 'div[1]' div중에서 1번째 태그

driver.find_element(By.XPATH,'//*[@id="query"]').send_keys('xpath')
driver.find_element(By.XPATH,'//*[@id="sform"]/fieldset/button').click()
driver.back()
driver.quit()
from selenium import webdriver
from selenium.webdriver.common.by import By

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

#1. 돋보기 버튼 선택(동적페이지div. search -> search.on)

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()

05. selenium과 beautifulsoup함께 이용하기

#현재 화면의 html 코드 가져오기
driver.page_source

#불러오기
from bs4 import BeautifulSoup
req = driver.page_source #html 소스담기
soup = BeautifulSoup(req,'html.parser')

#beautiful soup을 통해 원하는 데이터 제어 
soup.select('.post-item') 

contents = soup.select('.post-item')
len(contents)

contents[2]
driver.quit()

06. 셀프 주유소 실습

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

from selenium import webdriver
from selenium.webdriver.common.by import By
#팝업창 안뜰시, 
driver = webdriver.Chrome("../driver/chromedriver")
driver.get(url)
time.sleep(3)

#팝업창 뜰시, 
def main_get():

    #페이지 접근
    url = "https://www.opinet.co.kr/searRgSelect.do"
    driver = webdriver.Chrome("../driver/chromedriver")
    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) 사이트에서 '시','구' 값 리스트로 가져오기

#지역: 시/도 (객체 가져옴,변수sido_list_raw에 넣어줌)
sido_list_raw = driver.find_element(By.ID, "SIDO_NM0")
sido_list_raw.text

#sido_list라는 변수에 넣고 option값들 찾기 
sido_list = sido_list_raw.find_elements(By.TAG_NAME,"option")
len(sido_list),sido_list[17].text

#option value에 들어간 이름과 tag(text)이름이 다름('value'속성값 가져오기)
sido_list[1].get_attribute("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]
 

#가장 앞부분 '' slicing으로 없애주기 
sido_names = sido_names[1:]
sido_names
    
#'시' 태그 바꿔주기(사이트에서)
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") #자식태그(여러개이므로 elements)
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])

3) 엑셀로 '시','구'에 해당하는 값 저장하기

#방법1: css_selector로 엑셀 저장
driver.find_element(By.CSS_SELECTOR, "#glopopd_excel").click()

#방법2: xpath를 통한 excel 저장 
driver.find_element(By.XPATH, '//*[@id="glopopd_excel"]').click()

#방법3: id를 통한 excel저장
element_get_excel = driver.find_element(By.ID,"glopopd_excel")
element_get_excel.click()
import time
from tqdm import tqdm_notebook

#gu_name에는 gu이름들이 들어가있음 
#for문(서울로 고정해서 25구 안에서 엑셀다운받을 예정)
for gu in tqdm_notebook(gu_names): #tqdm에 넣는이유: 눈으로 진행상황보기위해
        element = driver.find_element(By.ID,"SIGUNGU_NM0")
        element.send_keys(gu)
        time.sleep(3)
        
        element_get_excel = driver.find_element(By.CSS_SELECTOR,"#glopopd_excel").click()
        time.sleep(3)
         
driver.close()

4) 데이터 정리하기

import pandas as pd
from glob import glob


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


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


#하나만 읽어보기
#header=2주는 이유: 엑셀을 기준으로 1,2행에 내용이 없기때문 그래서 2이후로 컬럼 가져오라고 해더값을 줌 
tmp = pd.read_excel(stations_files[0],header=2)
tmp.tail(2)


#for문을 통해 다 담아주기 
tmp_raw = []
for file_name in stations_files:
    tmp = pd.read_excel(file_name,header=2)
    tmp_raw.append(tmp
tmp_raw


#station_raw라는 변수에 tmp_raw를 데이터프레임 형식으로 바꾼 값을 넣어줌 
station_raw = pd.concat(tmp_raw)
station_raw


#dtype확인 : 문자열 + int 
station_raw.info()


station_raw.columns


#필요한 컬럼만 가져오기
stations = pd.DataFrame({
    "상호" : station_raw["상호"],
    "주소" : station_raw["주소"],
    "가격" : station_raw["휘발유"],
    "고급휘발유" : station_raw["고급휘발유"],
    "셀프" : station_raw["셀프여부"],
    "상표" : station_raw["상표"],
})
stations.tail()


#주소를 기준으로 어느구에 해당하는지 데이터 뽑아주기, 스플릿해서 리스트 형태로 '구'값 담아 데이터프레임에 추가
	#방법1
	stations["구"] = [eachAddress.split()[1] for eachAddress in stations["주소"]]
	stations
    
    #방법2
    stations["주소"] #스플릿으로 띄어쓰기부분 띄어서 리스트형태로 담아주기 
	for eachAddress in stations["주소"]:
    	print(eachAddress.split()[1]) #1번만 추출해서 '구'값만 가져오기 
        
        
#잘가져왔는지 데이터 확인
stations["구"].unique(),len(stations["구"].unique())


[참고]: 만약 데이터값이 많이나온경우
#만약 데이터값이 27개 나온경우? 
stations[stations["구"] == "서울특별시"]
stations.loc[stations["구"]== "서울특별시","구"] = "성동구"
stations[stations["구"] == "특별시"]
stations.loc[stations["구"]== "특별시","구"] = "도봉구"


#가격 부분 연산을 위해 데이터형 변환 object -> float 숫자형으로
stations["가격"] = stations["가격"].astype("float") 


#가격 정보가 있는 주유소만 사용하기
stations = stations[stations["고급휘발유"] !="-"]
stations.tail()


#object형 float로 변경하기(연산을 위해 데이터형 변환)
stations["고급휘발유"] = stations["고급휘발유"].astype("float") 


#인덱스 재정렬후 필요업는 인덱스 삭제
stations.reset_index(inplace=True)
del stations["index"]
stations.head()

5) 주유가격정보 시각화

#시각화 하기위한 한글화
import matplotlib.pyplot as plt
import seaborn as sns
import platform
from matplotlib import font_manager, rc

get_ipython().run_line_magic("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(frame=path).get_name()
    rc("font", family=font_name)
else:
    print("Unknown system sorry")
#boxplot(feat. pandas)
stations.boxplot(column="고급휘발유",by="셀프",figsize=(12,8))


#boxplot(feat. seaborn) 색이 들어감 
plt.figure(figsize=(12,8))
sns.boxplot(x="셀프", y="가격",data=stations, palette="Set3")#palette 스타일
plt.grid(True)
plt.show()

#boxplot(feat.seaborn) - 상표에 따른, 
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)


# 가장 비싼 주유소 10개
stations.sort_values(by="가격",ascending=False).head(10)


#가장 값싼 주유소 10개 
stations.sort_values(by="가격",ascending=True).head(10)


#구별 가격 평균값 
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개의 댓글