1 크롤링 자동화 1

2018년 6월 13일 제7회 전국지방선거가 현재 시간 기준(2018-05-25) 19일 남아있다. 이에 따라서 대진표가 정해지고 시시각각 다양한 여론조사 기관에서 광역자치단체장에 대한 여론조사결과가 갱신되고 있다. 이를 매일 수작업으로 가져오는 것은 비현실적이라 Azure, AWS 클라우드 컴퓨터를 저렴하게 임대해서 자동으로 데이터를 긁어올 수 있도록 크롤링 서버를 구축해본다.

크롤링 자동화

2 크롤링 서버

2.1 크롤링 R 코드

먼저 위키백과사전, 대한민국 제7회 지방 선거 여론 조사 웹페이지에서 과역자치단체장 여론조사결과를 긁어오는 R 코드를 작성한다.

상기 웹사이트에서 작성된 R 코드를 바탕으로 크롤링 R스크립트를 작성한다.

파일명을 crawl_local7_survey.R 파일로 저장한다.

# crawl_local7_survey.R
library(tidyverse)
library(rvest)
library(lubridate)
library(glue)

# 1. 데이터 -----
## 1.1. 제 7 회 지방선거 여론조사 -----
seven_url <- "https://ko.wikipedia.org/wiki/대한민국_제7회_지방_선거_여론_조사"
sido_v <- c("서울특별시장","인천광역시장","경기도지사","강원도지사","대전광역시장","세종특별자치시장","충청남도지사","충청북도지사","광주광역시장","전라남도지사","전라북도지사","부산광역시장","대구광역시장","울산광역시장","경상남도지사","경상북도지사","제주특별자치도지사")

crawl_survey <- function(sido_index) {
  sido_df <- read_html(seven_url) %>%
    html_nodes("table") %>%
    .[[sido_index+1]] %>%
    html_table(fill=TRUE)

  sido_df <- sido_df %>%
    mutate_at(vars(contains("당")), funs(str_replace_all(., "%", ""))) %>%
    mutate_at(vars(contains("기타")), funs(str_replace_all(., "%", ""))) %>%
    mutate_at(vars(contains("응답")), funs(str_replace_all(., "명|,", "")))

  sido_df <- sido_df %>% filter(! row_number() %in% c(1)) %>%
    separate("조사 기간", into=c("시작일", "종료일"), sep="\\~") %>%
    separate(시작일, into=c("월", "일"), sep=" ") %>%
    mutate(월 = str_extract(월, "[0-9]+"),
            일 = str_extract(일, "[0-9]+"))  %>%
    mutate(조사일 = ymd(str_c("2018-", 월, "-", 일))) %>%
    select(-월, -일, -종료일) %>%
    mutate("시도명" = sido_v[sido_index])

  return(sido_df)
}

assign(sido_v[1], crawl_survey(1)) # 1.1    서울특별시장
assign(sido_v[2], crawl_survey(2)) # 1.2    인천광역시장
assign(sido_v[3], crawl_survey(3)) # 1.3    경기도지사
assign(sido_v[4], crawl_survey(4)) # 1.4    강원도지사
assign(sido_v[5], crawl_survey(5)) # 1.5    대전광역시장
assign(sido_v[6], crawl_survey(6)) # 1.6    세종특별자치시장
assign(sido_v[7], crawl_survey(7)) # 1.7    충청남도지사
assign(sido_v[8], crawl_survey(8)) # 1.8    충청북도지사
assign(sido_v[9], crawl_survey(9)) # 1.9    광주광역시장
assign(sido_v[10], crawl_survey(10)) # 1.10 전라남도지사
assign(sido_v[11], crawl_survey(11)) # 1.11 전라북도지사
assign(sido_v[12], crawl_survey(12)) # 1.12 부산광역시장
assign(sido_v[13], crawl_survey(13)) # 1.13 대구광역시장
assign(sido_v[14], crawl_survey(14)) # 1.14 울산광역시장
assign(sido_v[15], crawl_survey(15)) # 1.15 경상남도지사
assign(sido_v[16], crawl_survey(16)) # 1.16 경상북도지사
assign(sido_v[17], crawl_survey(17)) # 1.17 제주특별자치도지사

sido_list <-  mget(sido_v)
sido_survey_df <- map_df(sido_list, bind_rows)

## 1.2. Save Data -----
sido_survey_df %>% write_rds(glue("/home/rstudio/shiny/sido_survey_", format(Sys.Date(), "%Y-%m-%d"), ".rds"))

2.2 쉘스크립트 작성

crawl_local7_survey.R 코드를 실행할 때, /usr/bin/Rscript를 사용하게 되면 대한민국 제7회 지방 선거 여론 조사 웹페이지에서 광역자치단체장에 해당되는 여론조사결과만 추려 데이터프레임으로 변환하여 sido_survey_2018-05-25.rds 같은 파일로 저장하게 된다.

이때 crawl_local7_survey.sh 배쉬 쉘스크립트 파일을 다음과 같이 작성한다. 아래 배쉬 쉘스크립트는 crawl_local7_survey.R 코드를 Rscript 프로그램으로 구동시키는 역할을 한다.

#!/bin/bash

/usr/bin/Rscript /home/rstudio/shiny/crawl_local7_survey.R

2.3 크론(cron) 등록 2

sudo crontab -e 명령어를 넣게 되면 특정 시간이 되면 자동으로 프로그램을 실행시킬 수가 있다. 이를 위해서 * * * * * /home/rstudio/shiny/crawl_local7_survey.sh > /home/rstudio/shiny/crawl.sh.log 2>&1와 같이 하여 매 1분마다 코드를 자동실행시켜 정상적으로 동작하는지 파악하고 매 1분마다 정상적으로 데이터를 가져오는 것이 확인되면 #으로 주석처리하고 나서 0 7 * * * /home/rstudio/shiny/crawl_local7_survey.sh을 작성하여 매일 7시마다 일 1회 데이터를 가져오도록 한다.

# * * * * * /home/rstudio/shiny/crawl_local7_survey.sh > /home/rstudio/shiny/crawl.sh.log 2>&1
0 7 * * * /home/rstudio/shiny/crawl_local7_survey.sh

2.4 크론작업 확인

크론탭(crontab)이 정해진 시간 실행이 되면 sido_survey_2018-05-25.rds, crawl.sh.log 파일이 생성된다. 그리고 제대로 실행이 되었는지는 크론을 실행시켜 남긴 로그 cat crawl.sh.log를 열어보고 정상적으로 동작이 된 것을 확인한다.

ubuntu@ip-xxx-xx-xx-xxx:/home/rstudo/shiny$ ls -al
total 32
drwxrwxrwx 2 root   root    4096 May 25 07:47 .
drwxr-xr-x 5 root   root    4096 May 25 06:15 ..
-rw-r--r-- 1 ubuntu ubuntu  2812 May 25 06:20 crawl_local7_survey.R
-rwxrwxr-x 1 ubuntu ubuntu    76 May 25 07:29 crawl_local7_survey.sh
-rw-r--r-- 1 root   root    2887 May 25 07:51 crawl.sh.log
-rw-r--r-- 1 root   root   11717 May 25 07:51 sido_survey_2018-05-25.rds
ubuntu@ip-xxx-xx-xx-xxx:/home/rstudo/shiny$ cat crawl.sh.log
── Attaching packages ─────────────────────────────────────── tidyverse 1.2.1 ──
✔ ggplot2 2.2.1.9000     ✔ purrr   0.2.4
✔ tibble  1.4.2          ✔ dplyr   0.7.4
✔ tidyr   0.8.0          ✔ stringr 1.3.0
✔ readr   1.1.1          ✔ forcats 0.3.0
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
Loading required package: xml2

Attaching package: ‘rvest’

The following object is masked from ‘package:purrr’:

    pluck

The following object is masked from ‘package:readr’:

    guess_encoding

Loading required package: methods

Attaching package: ‘lubridate’

The following object is masked from ‘package:base’:

    date
.....