R Crawler 5

RSelenium으로 수집하기

Dr.Kevin 1/29/2018

Selenium은 웹브라우저를 자동화해주는 소프트웨어입니다. 주로 웹어플리케이션 테스트를 자동화하는 목적으로 사용되곤 합니다만 사용자에 따라 활용할 수 있는 범위는 무궁무진하다고 할 수 있습니다.

Selenium으로 하나의 원격 브라우저를 연 다음, 사람이 웹 서핑을 하듯이 웹페이지를 열고 IDPW를 입력하게 할 수도 있고, 마우스가 이곳 저곳 돌아다니면서 클릭하는 것도 흉내낼 수 있습니다. 이런 이유로 Selenium을 웹크롤링에 활용할 수 있게 된 것입니다.

RSelenium은 R에서 Selenium을 실행시키는 것입니다. 그러므로 다른 언어(예컨데, Python)에서도 당연히 Selenium을 사용할 수 있습니다.

필수 프로그램 설치

RSelenium을 실행시키려면 몇 가지 프로그램을 미리 설치해야 합니다. 아마 대부분 Windows 운영체제를 사용하고 계실테고, Mac과 Linux를 사용하시는 분도 많을 겁니다. 사실 Linux를 쓰시는 분들이라면 컴퓨터 전문가에 가까울 겁니다. 그리고 Mac이 Linux 운영체제를 빌려쓴(?) 것이라고도 하니 이 블로그에서는 Windows와 Mac 운영체제별 설치방법을 간단하게 정리해볼까 합니다.

Java 설치

JDK (Java SE Development Kit)

위 링크를 따라 들어가면 아래 그림과 같이 웹페이지가 보입니다. JDK는 여러 버전이 있지만 이번에는 “8u161” 버전을 설치해보도록 하겠습니다. 아래 그림에서 Accept License Agreement를 체크한 후 각자 자신의 버전에 맞는 파일을 선택합니다.

Windows 사용자는 자신의 컴퓨터에서 Windows 비트수를 먼저 확인한 후에 해당 파일을 설치하시기 바랍니다. 64비트 사용자라면 64비트만 설치하셔도 되지만 32비트도 함께 설치하는 편이 좋다고 하니 참고하시기 바랍니다.

Mac 사용자는 macOS만 선택해서 다운로드 받은 후 (별다른 설정을 건드릴 필요 없이) 그냥 따라가면서 설치하면 됩니다.

참고! rJava 패키지에 의존하는 R 패키지를 사용하려면 rJava를 불러와야 합니다. Java를 설치했음에도 불구하고 rJava 불러오기가 되지 않는 경우가 발생하는 데요. 그럴 때는 아래와 같이 Java 설치 경로를 설정해주어야 합니다.

# Java 설치 경로(폴더) 설정하기 

# for Windows (아래 경로는 예시이므로 자신의 컴퓨터에서 확인하시기 바랍니다!)
Sys.setenv(JAVA_HOME = "C:/Program Files/Java/jre1.8.0_161/")

# for Mac (아래 경로는 예시이므로 자신의 컴퓨터에서 확인하시기 바랍니다!)
Sys.setenv(JAVA_HOME = "/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/jre")

Selenium Server Standalone 설치

Selenium Server Standalone

위 링크에 들어가서 가장 최신 버전의 파일을 다운로드합니다. 오늘(2018년 1월 29일) 기준으로는 3.8 버전이 가장 최신이군요. 3.8 폴더를 클릭하면 여러 가지 파일이 보일텐데요. 그 중에서 selenium-server-standalon-3.8.1.jar을 다운로드하고 적당한 장소에 저장하면 됩니다. 저는 WebDriver라는 폴더를 만들어서 그 안에 저장했습니다.

Chrome Driver 설치

Chrome Driver

마지막으로 Chrome Driver을 설치합니다. 역시 위 링크에 들어가면 최신 버전을 확인할 수 있습니다. 오늘 기준으로는 2.35가 가장 최신 버번입니다. 바로 아래 Downloads를 클릭한 후 원하는 버전을 선택하면 운영체제별로 zip 파일이 저장되어 있습니다. 압축을 해제하면 chromedriver 파일이 남습니다. 각자 맞는 파일을 선택해서 저장하도록 합니다. 저는 WebDriver라는 폴더에 옮겨 압축을 해제했습니다.

Selenium Server 수동으로 실행

이제 위에서 설치한 프로그램을 미리 실행시켜야 합니다. Windows 사용자는 cmd에서, Mac 사용자는 terminal에서 실행시키면 됩니다. 운영체제별로 cmd나 terminal을 열고 Chrome Driver가 설치된 폴더로 이동한 다음 아래와 같이 명령어를 실행합니다. x.x.x부분은 selenium server standalone version을 입력합니다.

  • Mac 사용자 (terminal에서 아래 명령 실행) java -Dwebdriver.chrome.driver="chromedriver" -jar selenium-server-standalone-x.x.x.jar -port 4445

  • Windows 사용자 (cmd에서 아래 명령 실행) java -Dwebdriver.chrome.driver="chromedriver.exe" -jar selenium-server-standalone-x.x.x.jar -port 4445

위 명령을 실행시켰을 때 로그 맨 아래에 INFO - Selenium Server is up and running이라고 뜨면 정상적으로 실행되고 있는 것입니다. 축하합니다!

RSelenium 실행하기

여기까지 따라오느라 고생 많았습니다. RSelenium을 이용하여 아주 간단한 예제를 하나 실행해보겠습니다.

먼저 RSelenium 패키지가 설치되어 있는지 확인하고, 설치되었으면 library() 함수로 불러옵니다. 그리고 remoteDriver() 함수를 이용하여 리모트 브라우저를 하나 띄웁니다. 아래 명령어를 실행하면 빈 크롬 브라우저가 하나 생길 것입니다.

# 필요 패키지를 불러옵니다.
library(RSelenium)
library(httr)
library(rvest)
library(dplyr)
library(stringr)
library(magrittr)

# 리모트 드라이버를 설정합니다.
remote <- remoteDriver(remoteServerAddr = "localhost",
                       port = 4445L,
                       browserName = "Chrome")

# 리모트 브라우저를 엽니다.
remote$open()

그리고나서 우리가 원하는 웹사이트에 접속해보겠습니다.

# 리모트 브라우저에서 웹사이트를 접속합니다.
remote$navigate("http://naver.com")

신기하게도 네이버에 접속이 됩니다. 이쯤에서 Selenium이 어떻게 작동하는지 아주 조금이나마 감을 잡았을 것이라고 생각합니다.

그럼 웹크롤러로 어떻게 기능하는지 실시간 검색어를 수집하는 방법을 통해 설명하겠습니다. 현재 접속되어 있는 웹페이지의 HTML을 다음과 같이 하면 읽어올 수 있습니다.

# 현재 접속된 웹페이지의 HTML을 읽습니다.
html <- remote$getPageSource() %>% `[[`(1)

# 실시간 검색어만 추출하고 데이터프레임으로 저장합니다.
read_html(html) %>% 
  html_nodes(css = "span.ah_k") %>% 
  html_text() %>% 
  head(n = 20L) %>% 
  data.frame() %>% 
  set_colnames("searchWords")
##        searchWords
## 1    리버풀 맨시티
## 2    식목일 공휴일
## 3           식목일
## 4           리버풀
## 5    고품격 짝사랑
## 6       라디오스타
## 7           넷마블
## 8           안희정
## 9           차세찌
## 10          기상청
## 11        부산날씨
## 12        다우지수
## 13        미국증시
## 14          한채아
## 15 수요미식회 곱창
## 16        대구날씨
## 17          경조증
## 18        오늘날씨
## 19        서울날씨
## 20          유아인

이번에는 더욱 신기한 것을 하나 더 보여드리고 마무리하도록 하겠습니다. 바로 네이버 로그인 과정을 Selenium에서 실행되도록 하는 것입니다. 그러니까 로그인 창에서 자신의 IDPW를 입력하고 로그인 버튼을 클릭하는 것이죠.

이를 위해 ID 입력칸, PW 입력칸, 그리고 로그인 버튼 등 각각의 HTML element에서 CSS SelectorXpath를 확인해야 합니다. 이제는 원하는 HTML element를 찾는 것쯤은 식은 죽 먹기라고 할 수 있겠죠? 크롬 개발자도구의 Elements 창에서 타겟 HTML element로 이동한 후 마우스 오른쪽 버튼을 클릭하면 Copy 메뉴가 있습니다. 그 하위 메뉴로 Copy selector 또는 Copy Xpath를 선택하면 각각 CSS Selector 또는 Xpath를 복사해올 수 있습니다.

이번 예제에서는 Xpath를 사용해보도록 하겠습니다. ID 입력창PW 입력창, 그리고 우측에 있는 녹색 로그인 버튼HTML element를 찾고 마우스 오른쪽 버튼을 클릭한 후 메뉴에서 Copy Xapth를 선택합니다. 그러면 다음과 같은 값을 복사해올 수 있을 것입니다.

  • ID : //*[@id="id"]
  • PW : //*[@id="pw"]
  • Login button : //*[@id="frmNIDLogin"]/fieldset/span/input

이제 findElement()를 이용하여 로그인을 해보겠습니다.

# 아이디랑 비밀번호 입력란을 설정합니다.
# 아래의 2가지 방법 중 하나를 선택하면 됩니다. 

# 1번 방식 : xpath로 설정 
id <- remote$findElement(using = "xpath", value = '//*[@id="id"]')
pw <- remote$findElement(using = "xpath", value = '//*[@id="pw"]')

# 2번 방식 : css selector로 설정
id <- remote$findElement(using = "css selector", value = "input#id")
pw <- remote$findElement(using = "css selector", value = "#pw")

IDPW와 입력란을 설정했으면, sendKeysToElement() 함수를 이용하여 IDPW를 입력합니다.

# 아이디와 비밀번호를 입력합니다.
id$sendKeysToElement(list("자신의 ID"))
pw$sendKeysToElement(list("자신의 PW"))

위와 같이 코드를 실행하니 각각의 창에 해당 문자가 입력되는 것이 보이죠? Selenium은 재미있고 신기한 도구입니다.

마지막으로 로그인 버튼을 설정하고 clickElement() 함수로 클릭해보겠습니다.

# 로그인 버튼을 설정합니다. 
btn <- remote$findElement(using = "xpath", 
                          value = '//*[@id="frmNIDLogin"]/fieldset/span/input')

# 로그인 버튼을 클릭합니다.
btn$clickElement()

이제 로그인 되었습니다. 로그인 되기 전에 보이지 않았던 (메일 등) 항목들도 로그인 후에는 보이게 됩니다. 즉, 웹크롤링을 할 때 로그인해야 보이는 정보는 RSelenium을 이용하여 간단하게 해결할 수 있다는 것을 의미합니다.

RSelenium을 끝마치려면 리모트 브라우저를 닫아주어야 합니다.

# 리모트 브라우저를 닫습니다.
remote$close()

그리고 Windows의 cmd나 Mac의 terminal로 가서 ctrl + c를 눌러 현재 실행 중인 Selenium Server도 종료해주어야 되겠죠?

이상으로 RSelenium을 활용한 웹크롤링에 대해서 간단하게 살펴보았습니다. RSelenium 패키지의 함수에 대해서 심도 있는 학습을 원하시면 여기를 방문해보시기 바랍니다.

다음 포스팅에서는 Open API를 활용하여 공공데이터를 수집하는 방법을 사례와 함께 알아보도록 하겠습니다.

Written on January 29, 2018