Selenium, BeautifulSoup

svenskpotatis·2023년 9월 9일
0

유가분석 강의 숙지사항

  • 기초 예제 블로그 업데이터(https://pinkwink.kr/)
  • selenium 문법 업데이트
    기존: find_element_by_css_selector('tag')
    현재: find_element(By.CSS_SELECTOR('tag'))

Beautiful Soup 만으로 해결할 수 없는 것

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

📌 Selenium

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

driver = webdriver.Chrome()
driver.get('사이트 주소')

driver.quit()
  • 화면 크기: maximize_window(), minimize_window(), set_window_size(n, n)
# 화면 최대 크기 설정
driver.maximize_window()

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

# 화면 크기 설정
driver.set_window_size(600, 600)
  • 새로고침, 뒤로가기, 앞으로 가기: refresh(), back(), forward()
# 새로 고침
driver.refresh()

# 뒤로 가기
driver.back()

# 앞으로 가기
driver.forward()
  • 클릭: click()
first_content = driver.find_element(By.CSS_SELECTOR, 'selector')
first_content.click()
  • 탭: window.open(), switch_to.window(), window_handles, close()
  • execute_script: 자바스크립트
# 새로운 탭 생성
driver.execute_script('window.open("https://www.naver.com")')  

# 탭 이동
driver.switch_to.window(driver.window_handles[0])
len(driver.window_handles)  # 현재 다룰 수 있는 탭

# 탭 닫기
driver.close()
  • 전체 종료: driver.quit()

  • 화면 스크롤

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

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

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

# 특정 태그 지점까지 스크롤 이동
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()
  • 스크린샷
# 현재 보이는 화면 스크린샷 저장
driver.save_screenshot('./last_height.png')  # ./ : 현재 위치

검색어 입력

  • CSS_SELECTOR
  • XPATH
    //: 최상위
    *: 자손 태그
    /: 자식 태그
    div[1]: div 중에서 1번째 태그
driver.find_element(By.XPATH, '//*[@id="query"]').send_keys('xpath')  # 검색어
driver.find_element(By.XPATH, '//*[@id="sform"]/fieldset/button').click()
  • 선택
# 1. 돋보기 버튼을 선택
from selenium.webdriver import ActionChains

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

📌 Selenium + BeautifulSoup

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

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

Self Oil Station Price Analysis

셀레니움 설치

  • 윈도우, mac(intel)
    • conda install selenium
  • mac(m1)
    • pip install selenium
  • chromedriver

데이터 확보

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.XPATH, '//*[@id="glopopd_excel"]').click()
    time.sleep(3)
  • time: 브라우저 로딩 기다림
  • tqdm: 진행 상황 확인

데이터 정리

import pandas as pd
from glob import glob
  • glob
# 파일 이름 한 번에 가져오기
glob('../data/지역_*.xls')

# 파일명 저장
station_files = glob('../data/지역_*.xls')
station_files[:5]
  • pd.concat: 형식이 동일하고 연달아 붙이기만 할 때
  • 데이터형 변환
# 가격 데이터형 변환 object => float

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

시각화

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('Unknown system. sorry~~~')
  • boxplot
# 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='Set1')
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)
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

0개의 댓글