👨🏼‍💻

ch2 - 3. Selenium으로 크롤링

Selenium 이란?

Selenium 은 웹 어플리케이션을 자동으로 테스팅할 때 사용하는 프레임 워크입니다. Python 과 많은 언어를 지원합니다. 앞에서 BeautifulSoup를 열심히 공부한 후 Web 크롤링에 사용하기 시작하면 더 필요한 기능이 생길 것입니다. 몇가지 예시 상황을 들어보겠습니다.
  1. 특정 페이지를 들어가서 정보를 가져온 후 다시 원래 페이지로 돌아와서 정보를 얻고 싶을 때
  1. 페이지에서 버튼들을 자동으로 누른 후 그 안의 정보를 가져오고 싶을 때
  1. 목록 페이지에 있는 링크들을 차례로 들어가 정보를 순차적으로 가져오고 싶을 때
위 세 가지 경우를 모두 Selenium으로 조작할 수 있습니다.

Selenium 설치하기

Selenium을 사용하기 위해서는 웹 브라우저 드라이버와 'selenium' 라이브러리를 설치해야 합니다. 드라이버는 크롬을 대상으로 진행하였습니다.
(크롬 드라이버 설치 링크 : http://chromedriver.chromium.org/downloads )
pip install selenium

Selenium

웹 브라우저는 Script 코드를 실행시킨 후 HTML 소스코드를 DOM의 형태로 나타낸다. 보통의 크롤러는 HTML 소스코드 내용에 접근하기에 페이지 내의 이벤트(ex. 버튼 클릭, 추가 창)에 대한 처리가 불가능하지만, 'selenium' 은 브라우저를 동반하여 DOM 에 직접 접근하여 크롤링할 수 있기 때문에 동적 웹을 크롤링하는데 효과적입니다. 우선 google 에 접속하는 코드를 작성해보겠습니다.
from selenium import webdriver # 설치한 크롬 드라이버의 경로 path = "C:/crawling/chromedriver.exe" driver = webdriver.Chrome(path) driver.get('https://www.google.com') # 드라이버를 닫습니다. driver.close()
경로에 한글이 있으면 오류가 발생할 수 있습니다. 또한 영문으로 되어있음에도 경로 코드에서 오류가 발생하는 경우에는 첫번째 쌍따옴표 앞에 r을 붙이면 해결됩니다.

Selenium 핵심 기능

'selenium' 의 강점은 드라이버를 동반하기 때문에 로그인, 버튼 클릭 및 동적 웹을 크롤링할 수 있는 것에 있습니다. BeautifulSoup 크롤링과 같은 방법으로 HTML element 에 접근하는 방식으로 사용됩니다. element 가 지정되면 해당 element 에 값을 전달하거나 버튼의 경우 클릭을 할 수 있습니다.
 

Element 접근하기

  1. 개발자 모드로 접근하여, 좌측 상단의 다음과 같은 아이콘을 눌러줍니다.
    1. notion imagenotion image
       
  1. 원하는 HTML element 를 클릭합니다.
    1. notion imagenotion image
       
  1. element 의 class, selector, name, id 등으로 element 에 접근합니다.
driver = webdriver.Chrome(path) # element 의 class name 으로 접근 driver.find_element_by_class_name( ) # element 의 selector 로 접근 driver.find_elements_by_css_selector( ) # element 의 name 으로 접근 driver.find_element_by_name( ) # element 의 xpath 로 접근 driver.find_element_by_xpath( ) # element 의 id 로 접근 driver.find_element_by_id( )
 

Element 에 Data 전송 및 클릭

element 에 접근했다면 해당 element 에 데이터를 전송하고, 클릭을 할 수 있습니다.
element = driver.find_element_by_name( ) element.send_keys('value') # element 에 value 값을 전송합니다. element.click( ) # element 를 click 합니다.
 

Selenium 브라우저 감추기

사용자의 설정에 따라 selenium 브라우저 생성하지 않고 크롤링 할 수 있다. 이 외에도 다양한 설정들을 추가적으로 설정할 수 있다.
from selenium import webdriver path = "C:/crawling/chromedriver.exe" chrome_options = webdriver.ChromeOptions() chrome_options.add_argument("headless") driver = webdriver.Chrome(path, chrome_options=chrome_options) driver.get("http://www.google.com") print(driver.title)
 

Selenium XPath

개발자 도구 상에서 주어지는 XPath를 가지고 크롤링에 더욱 유용하게 사용할 수 있습니다. (로그인 등) 원하는 부분의 복사는 오른쪽 클릭을 한 후 copy>copy XPath를 누르면 됩니다. xpath를 이용하면 원하는 element들도 손쉽게 가져올 수 있습니다.
driver.find_element_by_xpath('XPath의 경로 설정').click()
 

Selenium 활용 (1)

다음은 'selenium'을 이용하여 구글에서 'Paullab' 을 검색하는 코드입니다.
from selenium import webdriver import time path = "C:/crawling/chromedriver.exe" driver = webdriver.Chrome(path) driver.get('https://www.google.com') # 검색창의 name 을 이용하여 접근합니다. driver.find_element_by_name("q").send_keys("Paullab") time.sleep(1) # Google 검색 창에서 name이 btnK인 것을 찾아 클릭합니다. driver.find_element_by_name("btnK").click() # 드라이버를 종료합니다. driver.close()
 

Selenium 활용 (2)

배웠던 내용을 활용하면 다음과 같은 방식으로 로그인을 할 수 있습니다.
driver.find_element_by_name("id").send_keys("ID") # id 입력 time.sleep(1) driver.find_element_by_name("pw").send_keys("PW") # pw 입력 time.sleep(1) driver.find_element_by_name("login").click() # login 버튼 클릭
2번 째 라인의 time.sleep()은 다음 명령을 수행하기 전에 페이지가 로드되는 시간을 기다리게 할 때와
서버가 사용자를 기계로 인식하면 접근을 막는데, 이를 방지할 때 사용합니다.
 
다음은 네이버 로그인 예제문입니다.
다음(daum), 네이버(naver) 로그인 같은 경우 캡챠(CAPTCHA란, 사용자가 실제 사람인지 컴퓨터 프로그램인지를 구별하기 위해 사용되는 방법. 글자 인식 등의 방법이 활용됨.)가 걸리므로, 이 코드만 가지고 로그인을 하는 것은 불가능합니다. 이런 형식으로 하여 다른 사이트에도 적용시킬 수 있습니다.
from selenium import webdriver import time path = "C:/crawling/chromedriver.exe" driver = webdriver.Chrome(path) driver.get('https://www.naver.com') driver.find_element_by_class_name('lg_local_btn').click() driver.find_element_by_id('id').send_keys('아이디를 입력') time.sleep(1) driver.find_element_by_id('pw').send_keys('비밀번호를 입력') time.sleep(1) driver.find_element_by_class_name('btn_global').click() time.sleep(1) driver.close()
 
다음은 facebook 로그인 예제입니다.
from selenium import webdriver import time path = "C:/crawling/chromedriver.exe" driver = webdriver.Chrome(path) driver.get('https://www.facebook.com') driver.find_element_by_id('email').send_keys('전화번호 혹은 이메일') time.sleep(1) driver.find_element_by_id('pass').send_keys('비밀번호') time.sleep(1) driver.find_element_by_id('loginbutton').click() time.sleep(1) driver.close()
 

Selenium 활용 (3)

구글맵에서 자동으로 위치를 검색해주는 과정입니다.
from selenium import webdriver import time path = "C:/crawling/chromedriver.exe" driver = webdriver.Chrome(path) driver.get('https://www.google.co.kr/maps/') driver.find_element_by_name("q").send_keys("제주국제공항") # 검색창의 name 을 이용한 접근 time.sleep(1) driver.find_element_by_class_name("searchbox-searchbutton-container").click() # 검색창의 class name 을 이용한 접근 driver.close()

Selenium 활용 (4)

youtube에서 버튼을 자동으로 클릭 및 동적 크롤링 진행 과정 코드의 앞부분입니다.
from selenium import webdriver from selenium.webdriver.common.keys import Keys import time search=(input("검색어를 입력하세요.")) search= str(search.encode('utf-8')) search=search.replace("\\",'%').replace('x','').upper().replace("'","")[1:] #검색어를 사용자가 입력한 후 서버가 받을 수 있는 언어로 바꿔줍니다. driver = webdriver.Chrome(r'C:\Users\sub_account\Desktop\python\chromedriver') driver.get('https://www.youtube.com/results?search_query='+search) body = driver.find_element_by_tag_name("body") num_of_pagedowns = 4 #페이지 다운 버튼 클릭 횟수를 지정해줍니다. time.sleep(1.5) while num_of_pagedowns: body.send_keys(Keys.PAGE_DOWN) time.sleep(1) #페이지가 내려가고 로딩 시간을 기다려줍니다. num_of_pagedowns -= 1 #버튼을 한번씩 클릭하여 내려줍니다. try: driver.find_element_by_xpath().click() except: None html = driver.page_source
 

Selenium 활용 (5)

instagram 검색어를 입력 받아 해당 검색어의 최신 순으로 5개의 게시물에 등장하는 해시태그 목록과 해당 해시태그의 등장 횟수를 출력해주는 코드입니다.
from selenium import webdriver import time path = "/usr/local/bin/chromedriver" keyword = input("키워드를 입력하세요 : ") page = [] hashtag = {} driver = webdriver.Chrome(path) # insta 는 다음과 같은 url 구조를 지닙니다. driver.get('https://www.instagram.com/explore/tags/' + keyword) time.sleep(2) for i in driver.find_elements_by_css_selector('.v1Nh3 > a'): page.append(i.get_attribute('href')) # 검색결과 없을 경우 if len(page) == 0: print("검색 결과가 없습니다. ") driver.close() exit() # 5개의 페이지에 관해서만 크롤링합니다. page = page[:5] for num, url in enumerate(page,1): time.sleep(1) driver.get(url) # 탐색 도중 게시물이 삭제되는 등의 오류 페이지 나타날 경우 if driver.find_elements_by_css_selector('.dialog-404'): continue body = driver.find_elements_by_css_selector('body') hashtag_list = body[0].text.split('#')[1:] for ch in hashtag_list: ch = ch.split(' ')[0].split('\n')[0] # 처음 등장하는 단어인 경우 Dictionary 에 추가한다. if ch not in hashtag.keys(): hashtag[ch] = 1 else: hashtag[ch] += 1 # 탐색 상태를 표시해주기 위한 코드 print("test[{}/{}]".format(num, len(page))) time.sleep(1) driver.close() print(hashtag)
notion imagenotion image