Python/Web Crawling

[Web Crawling] Selenium

데이터 세상 2021. 5. 11. 20:08

Selenium(셀레니움)

  • 웹 브라우저의 자동화를 가능하게 하고 지원하는 다양한 도구와 라이브러리를 포함한 프로젝트
  • 웹 앱을 테스트 할 때 주로 사용하는 프레임워크
  • webdriver라는 api를 통해서 browser 제어
  • 동적인 환경에서 크롤링
  • 웹 테스트의 자동화

 

www.selenium.dev/documentation/ko/

 

Selenium 브라우저 자동화 프로젝트 :: Selenium 문서

Selenium 브라우저 자동화 프로젝트 Selenium은 웹 브라우저의 자동화를 가능하게 하고 지원하는 다양한 도구와 라이브러리를 포함한 프로젝트입니다. 브라우저와의 사용자 간의 상호 작용을 테스

www.selenium.dev

 

Selenium 라이브러리 설치

pip install selenium

 

browser driver 설치

Linux OS의 경우 다음 명령어로 chrome driver 설치 가능

apt install chromium-chromedriver

 

Selenium 요소 및 함수

Waits

  • selenium을 사용해 테스트 할 때 elements를 찾을 수 있도록 web page가 로딩이 끝날 때 까지 기다려야 함.
  • AJAX를 이용해 만든 web의 경우 리소스가 로드 하는데 부문별로 다를 수 있음.
  • 로딩이 완료 되기 전에 해당 element를 참조 ElementNotVisibleException, NoSuchElementException 에러 발생.
  • Explicit Waits : 특정 상태가 될때 까지 기다리고, 상태가 되면 바로 실행
  • Implicit Waits : 주어진 시간 까지 대기
  • ajax를 사용하지 않는 웹 사이트에서 단순하게 DOM구조만 변경되는 상황이면 Implicit wait를 사용해도 무방함.(DOM API 처리 속도는 굉장히 빠름.)
  • 최신 웹 사이트들은 대부분 ajax요청을 통해 웹 구조를 바꾸는 SPA(Single Page App)방식이 많음. 크롤링을 진행할 때 Explicitly wait을 이용하는 것이 좋음.

 

Selenium Method 및 API

Single Method

함수 설명
find_element_by_id(id) id 속성으로 요소를 하나 추출
find_element_by_name(name) name 속성으로 요소를 하나 추출
find_element_by_css_selector(query) css 선택자로 요소를 하나 추출
find_element_by_xpath(query) XPath를 지정해 요소를 하나 추출
find_element_by_tag_name(name) tag 이름이 name에 해당하는 요소를 하나 추출
find_element_by_link_text(text) 링크 텍스트로 요소를 하나 추출
find_element_by_partial_link_text(text) 링크의 child 요소에 포함돼 있는 텍스트로 요소를 하나 추출
find_element_by_class_name(name) 클래스 이름이 name에 해당하는 요소를 하나 추출

Multiple Method

함수 설명
find_elements_by_id(id) id 속성으로 요소를 여러 개 추출
find_elements_by_name(name) name 속성으로 요소를 여러 개 추출
find_elements_by_css_selector(query) css 선택자로 요소를 여러 개 추출
find_elements_by_xpath(query) XPath를 지정해 요소를 여러 개 추출
find_elements_by_tag_name(name) tag 이름이 name에 해당하는 요소를 여러 개 추출
find_elements_by_link_text(text) 링크 텍스트로 요소를 여러 개 추출
find_elements_by_partial_link_text(text) 링크의 child 요소에 포함돼 있는 텍스트로 요소를 여러 개 추출
find_elements_by_class_name(name) 클래스 이름이 name에 해당하는 요소를 여러 개 추출

XPath (XML Path Language)

  • W3C의 표준으로 XML(Extensible Markup Language)문서의 구조를 통해 경로(Path)위에 지정한 구문을 사용하여 항목을 배치하고 처리하는 방법을 기술하는 언어.
  • XML 표현보다 더 쉽고 약어로 되어 있으며, XSL변환(XSLT)과 XML지시자 언어(XPointer)에 쓰이는 언어로 XML 문서의 Node를 정의하기 위하여 경로식(Path Expression)을 사용

 

문법

표현 설명
nodename 노드명이 'nodename'인 노드 선택
/ 루트 노트로부터 선택
// 현재 노드로부터 문서상의 모든 노드 조히
. 현재 노드 선택
.. 현재 노드의 부모 노드 선택
@ 현재 노드의 속성 선택

 

DOM 요소에 적용할 수 있는 method

함수 설명
clea() 글자를 입력할 수 있는 요소의 글자를 지운다
click() 요소를 클릭한다
get_attribute(name) 요소의 속성 중에 name에 해당되는 속성의 값을 추출한다
is_displayed() 요소가 화면에 출력되는지 확인한다
is_enabled() 요소가 활성화 되었는지 확인한다
is_selected() 체크박스 등의 요소가 선택 상태인지 확인한다
screenshot(filename) 화면을 캡쳐해서 filename으로 저장한다
send_keys(value) 키를 입력한다. 일반적으로 text 데이터를 보낸다
submit() 입력 양식을 전송한다
value_of_css_property(name) name에 해당하는 CSS 속성 값을 추출한다

 

Selenium Sample Code

web page 조회 시 chrome browser 실행 없이 정보 가져오기

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome('chromedriver', chrome_options=chrome_options)

url = 'https://www.naver.com'
driver.get(url)

 

객체 id나 class name으로 정보 가져오기

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome('chromedriver', chrome_options=chrome_options)
url = 'https://www.naver.com'
driver.get(url)


input_elem = driver.find_element(By.ID, 'query')
input_elem.send_keys('서울 날씨')
driver.find_element(By.ID, 'search_btn').click()
print(driver.find_element(By.CLASS_NAME, 'temperature_text').text)
print()
print(driver.find_element(By.CLASS_NAME, 'temperature_info').text)

 

동적 페이지의 정보를 selenium으로 접근하고 html 데이터는 BeautifulSoup을 이용해서 추출

# 멜론 인기차트 상위 50곡 크롤링
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup


# chromedriver 실행 파일이 별도로 존재하는 경우
# driver = webdriver.Chrome('c:/chromedriver.exe')     

# 설치된 chromedriver를 사용하는 경우
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome('chromedriver', chrome_options=chrome_options)

url = 'http://www.melon.com/chart/index.htm'
driver.get(url)          
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
                               
songs = soup.select('tr')[1:51]
idx = 0
for song in songs:                                        
	idx += 1
    title = song.select('div.ellipsis.rank01 > span > a')[0].text
    singer = song.select ('div.ellipsis.rank02 > a')[0].text  
    print(idx, title, singer, sep = ' | ')
driver.quit()

 

NAVER 검색창에 python을 검색하고 결과 확인하기

from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome('chromedriver', chrome_options=chrome_options)

driver.get('https://www.naver.com')
input_element = driver.find_element(By.ID, 'query')
input_element.send_keys('python')
input_element.send_keys(Keys.RETURN)

html = driver.page_source
bsObj = BeautifulSoup(html, 'html.parser')

ul_tag = bsObj.find('ul', {'class':'lst_type'})
lis = ul_tag.findAll('li')

for li in lis:
    a_tag = li.find('a')
    # print(a_tag['href'])
    print(a_tag.text)

 

Coffebean Store 정보 조회해서 CSV 파일로 저장하기

https://www.coffeebeankorea.com/store/store.asp

매장정보 팝업에서 "자세히보기" javascript를 실행해서 상세 매장 정보 조회하기

자세히보기에 마우스 오버 시 하단에 javascript 함수가 노출되어 있음

from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome('chromedriver', chrome_options=chrome_options)


def cfb_store_info(result):
    cb_url = 'https://www.coffeebeankorea.com/store/store.asp'
    
    for i in range (1, 30):
        driver.get(cb_url)
        time.sleep(2)
        try:
            driver.execute_script('storePop2(%d)'% i)
            time.sleep(2)
            html = driver.page_source
            bsObj = BeautifulSoup(html, 'html.parser')
            store_name_h2 = bsObj.select('div.store_txt > h2')
            store_name = store_name_h2[0].text
            store_info = bsObj.select('div.store_txt > table.store_table > tbody > tr > td')
            store_address = store_info[2].text
            store_phone = store_info[3].text
            result.append([store_name, store_address, store_phone])            
        except:
            continue
    
result = []
cfb_store_info(result)

data = pd.DataFrame(result,
                   columns=['매장명','주소','전화번호'])
data.to_csv('cfb_data.csv', index=False)
반응형

'Python > Web Crawling' 카테고리의 다른 글

[Web Crawling] Beautiful Soup  (0) 2022.04.27
[Web Crawling] Scraping & Crawling  (0) 2022.04.27