가능하면 RStudio 환경에서 모든 작업이 가능하도록 팬텀JS를 설치하고 나서 이를 윈도우 환경경로에 설정한다.
phantomjs-2.1.1-windows.zip
파일 압축을 푼다.\phantomjs-2.1.1-windows\bin
절대 경로명을 복사하여 윈도우 환경설정 경로에 추가한다.
C:\Users\.....\phantomjs-2.1.1-windows\bin
상기 작업을 수행하게 되면, 팬텀JS가 설치된 C:\Users\.....\phantomjs-2.1.1-windows\bin
경로에 상관없이 임의 디렉토리에서 phantomjs
명령어를 실행해도 명령이 실행된다.
D:\>phantomJS --version
2.1.1
자세한 사항은 다음 동영상을 참조한다.
윈도우 쉘환경에서 팬텀JS가 정상적으로 설치된 것이 확인되면 다음 단계로 운영체제에 맞는 system
, system2
, shell
등의 명령어로 R 환경에서 쉘명령을 직접 실행해본다.
xwMOOC.js
파일var page = require('webpage').create(); var url = 'http://statkclee.github.io/xwMOOC/'; page.open(url, function (status) { console.log(status); phantom.exit(); });
> system("phantomjs --version")
2.1.1
> system("phantomjs ./code/xwMOOC.js")
success
방송 3 사 8시 뉴스 혈투를 살펴보면 흥미로운 사실이 통계분석을 통해 나타난다. 이를 위해서 scrape_daum_jtbc.js
파일에 다음 JTBC 뉴스룸 시청률 정보를 가져오는데, 다음 SBS 8시 뉴스, 다음 MBC 뉴스데스크도 방송 시청률 데이터를 끌어오는 작업을 수행한다.
scrape_daum_jtbc.js
파일var webPage = require('webpage'); var page = webPage.create(); var fs = require('fs'); var path = 'data/daum_jtbc.html'; page.open('http://movie.daum.net/tv/ratings?tvProgramId=66868', function (status) { var content = page.content; page.render('fig/daum_jtbc.png'); fs.write(path, content, 'w'); phantom.exit(); });
# 0. 환경설정 --------------------------
# library(rvest)
# library(stringr)
# library(tidyverse)
# library(gganimate)
# library(ggthemes)
# library(extrafont)
# loadfonts()
# 1. 데이터 긁어오기 --------------------------
system("phantomjs ./code/scrape_daum_jtbc.js")
system("phantomjs ./code/scrape_daum_sbs.js")
system("phantomjs ./code/scrape_daum_mbc.js")
Sys.setlocale("LC_ALL", "C")
[1] "C"
jtbc_raw <- read_html("data/daum_jtbc.html") %>%
html_nodes(xpath='//*[@id="menuSlide"]/div[2]/div[1]/table[2]') %>%
html_table(fill = TRUE) %>%
.[[1]]
sbs_raw <- read_html("data/daum_sbs.html") %>%
html_nodes(xpath='//*[@id="menuSlide"]/div[2]/div[1]/table[2]') %>%
html_table(fill = TRUE) %>%
.[[1]]
mbc_raw <- read_html("data/daum_mbc.html") %>%
html_nodes(xpath='//*[@id="menuSlide"]/div[2]/div[1]/table[2]') %>%
html_table(fill = TRUE) %>%
.[[1]]
Sys.setlocale("LC_ALL", "Korean")
[1] "LC_COLLATE=Korean_Korea.949;LC_CTYPE=Korean_Korea.949;LC_MONETARY=Korean_Korea.949;LC_NUMERIC=C;LC_TIME=Korean_Korea.949"
웹에서 긁어온 방송 3사 데이터를 데이터 분석이 가능하고, 시각화가 가능한 형태로 데이터를 가공한다. 특히, 주별 사이클이 확연히 존재하기 때문에 이를 최대한 파악하기 용이한 형태로 작업한다.
# 2. 데이터 정제 ---------------------
jtbc_df <- jtbc_raw %>%
mutate(방송사 = "JTBC",
시청률 = as.numeric(str_replace(시청률, "%", "")) / 100,
날짜 = lubridate::ymd(str_replace(str_sub(날짜, 1, 10), "\\.", "-"))) %>%
select(방송사, 날짜, 시청률)
sbs_df <- sbs_raw %>%
mutate(방송사 = "SBS",
시청률 = as.numeric(str_replace(시청률, "%", "")) / 100,
날짜 = lubridate::ymd(str_replace(str_sub(날짜, 1, 10), "\\.", "-"))) %>%
select(방송사, 날짜, 시청률)
mbc_df <- mbc_raw %>%
mutate(방송사 = "MBC",
시청률 = as.numeric(str_replace(시청률, "%", "")) / 100,
날짜 = lubridate::ymd(str_replace(str_sub(날짜, 1, 10), "\\.", "-"))) %>%
select(방송사, 날짜, 시청률)
station_df <- bind_rows(jtbc_df, sbs_df) %>%
bind_rows(mbc_df) %>%
mutate(방송사 = factor(방송사, levels=c("JTBC", "SBS", "MBC")))
station_df %>% spread(방송사, 시청률) %>%
mutate(요일 = lubridate::wday(날짜, label=TRUE)) %>%
select(날짜, 요일, everything()) %>%
DT::datatable() %>%
DT::formatPercentage(c(2,3,4), digits=1)
방송 3사 최근 약 2개월 방송 시청률을 보면 손석희 앵커가 진행하는 주중에는 확연한 JTBC 우위, 손석희 앵커가 빠지는 금요일부터 토요일 일요일은 MBC와 SBS가 경쟁하는 추세가 명확히 확인된다.
# 3. 데이터 시각화 ---------------------
## 3.1. 정적 시각화
station_colors <- c("#d60cbb", "#1187c6", "#465977")
station_df %>%
ggplot(aes(x=날짜, y=시청률, color=방송사)) +
geom_line(size=1.1, alpha=0.3) +
geom_point(size=1.5, alpha=0.7) +
theme_tufte(base_family = "NanumGothic") +
labs(x="", y="시청률", title="방송3사 8시 뉴스 혈투") +
scale_y_continuous(labels=scales::percent) +
scale_x_date(date_labels = "%m-%d-%A",
breaks = seq(min(station_df$날짜), max(station_df$날짜), by="week")) +
scale_fill_manual(values= station_colors) +
theme(legend.position = "top",
axis.text.x=element_text(angle=90,hjust=1))
gganimate
팩키지를 활용하여 시각화할 경우 손석희 앵커의 주중 효과에 대해서 좀더 명확히 확인할 수 있다.
## 3.2. 동적 시각화
station_gg <- ggplot(station_df, aes(x=날짜, y=시청률, color=방송사)) +
geom_line(size=1.1, alpha=0.3) +
geom_point(aes(frame=날짜), size=3.7, alpha=0.7) +
theme_tufte(base_family = "NanumGothic") +
labs(x="", y="시청률", title="방송3사 8시 뉴스 혈투") +
scale_y_continuous(labels=scales::percent) +
scale_x_date(date_labels = "%m-%d-%A",
breaks = seq(min(station_df$날짜), max(station_df$날짜), by="week")) +
scale_fill_manual(values= station_colors) +
theme(legend.position = "top",
axis.text.x=element_text(angle=90,hjust=1))
gganimate(station_gg, "fig/jtbc_sbs_mbc.gif", ani.width = 800, ani.height = 600)