정보
-
업무명 : R을 이용한 과거 네이버/zum/구글 실시간 검색어 수집 후 코로나 관련 키워드 추출
-
작성자 : 박진만
-
작성일 : 2020-11-30
-
설 명 :
-
수정이력 :
내용
[개요]
-
안녕하세요? 웹 개발 및 연구 개발을 담당하고 있는 해솔입니다.
-
다년간 축적된 경험 (기상학 학술 보고서 및 국/영문 학술 논문 게재, 블로그 운영, IT 회사 웹 개발 담당) 및 노하우를 바탕으로 개개인에게 맞춤형 솔루션을 수행할 수 있습니다.
-
특히 재능 플랫폼 (크몽, 오투잡, 해피캠퍼스, 레포트 월드)에서 누구보다도 경쟁력 있는 가격으로 양질의 서비스를 제공하고 있습니다.
-
아스키 형식의 텍스트 (text) 파일부터 과학자료 형식 (HDF, H5, NetCDF, Grib, Grb) 및 Data Base (DB) 자료까지 다양한 형태의 자료를 이용하여 수집, 전처리, 분석, 시각화해 드립니다.
-
또한 웹 사이트에 대한 정보를 이용한 웹 크롤링 및 그에 따른 엑셀 및 DB 구축도 가능합니다.
-
아울러 기초 통계 (빈도분포, Prired t-test, Wilcoxn 등)에서 지도/비지도 학습을 통한 회귀모형 구축에 이르기 까지 효율적인 통계 정보를 제공합니다.
-
최근 대한민국의 후속위성인 천리안위성 2A호 웹 서비스 서브시스템 및 환경위성 2B호 통합 자료처리 서브시스템에 대한 웹 개발을 수행하였습니다.
-
-
그리고 해솔 블로그에서는 다양한 기상학/천문학 정보와 더불어 사무 자동화/프로그래밍 언어를 소개하오니 방문 부탁드립니다.
-
좋은 하루 보내세요.
[재능플랫폼] 오투잡
[재능플랫폼] 크몽
요청
[세부 사항]
-
R 스크립트를 이용한 과거 포털 사이트(네이버,zum,구글) 실시간 검색어 수집
-
수집된 자료를 이용한 워드 클라우드 시각화
완료
[사용 OS]
-
Windows 10
[사용 언어]
-
R v4.0.3
[소스 코드 - 인기 검색어 수집 코드]
library(RSelenium)
library(rvest)
library(stringr)
library(tidyverse)
library(data.table)
library(foreach)
library(httr)
library(webdriver)
library(seleniumPipes)
library(readxl)
library(foreach)
library(ggwordcloud)
library(wordcloud2)
library(htmlwidgets)
library(webshot)
# library(xlsx)
library(log4r)
library(readxl)
library(tcltk)
library(beepr)
#install.packages("noncompliance")
library(noncompliance)
Sys.setlocale("LC_ALL")
options(encoding = "UTF-8")
Sys.setenv(LANG = "en_US.UTF-8")
setWindowTab = function (remDr, windowId) {
qpath = sprintf("%s/session/%s/window", remDr$serverURL, remDr$sessionInfo[["id"]])
remDr$queryRD(qpath, "POST", qdata = list(handle = windowId))
}
getXpathText = function(xpath) {
remDr$getPageSource()[[1]] %>%
read_html() %>%
rvest::html_nodes(xpath = xpath) %>%
rvest::html_text() %>%
str_replace_all(pattern = "\n", replacement = " ") %>%
str_replace_all(pattern = "[\\^]", replacement = " ") %>%
str_replace_all(pattern = "\"", replacement = " ") %>%
str_replace_all(pattern = "\\s+", replacement = " ") %>%
str_trim(side = "both")
}
getCssText = function(css) {
remDr$getPageSource()[[1]] %>%
read_html() %>%
rvest::html_nodes(css = css) %>%
rvest::html_text() %>%
str_replace_all(pattern = "\n", replacement = " ") %>%
str_replace_all(pattern = "[\\^]", replacement = " ") %>%
str_replace_all(pattern = "\"", replacement = " ") %>%
str_replace_all(pattern = "\\s+", replacement = " ") %>%
str_trim(side = "both")
}
remDr = remoteDriver(
remoteServerAddr = "localhost"
, port = 5000L
, browserName = "chrome"
)
remDr$open()
getRootHandle = remDr$getWindowHandles()
getUrl = "http://rank.ezme.net/zum"
remDr$navigate(getUrl)
# 오늘날짜 가져오기
webElem <- remDr$findElement(value = "*")
webElem$getElementAttribute("webElement fields")
getHtmlText = remDr$getPageSource()[[1]]
getDate = getHtmlText %>%
read_html() %>%
rvest::html_nodes("input") %>%
html_attr("value")
## 날짜 획득 ##
getDate_L1 <- getDate[2]
## 시작날짜 - 끝날짜 설정 ##
st_date = as.Date("2018-01-01")
ed_date = as.Date(getDate_L1)- 1
target_date = as.character(seq(st_date,ed_date,by = "days"))
data_full = data.frame()
aa = 0
## 수집 시작 ##
for (d in target_date) {
aa = aa + 1
## 날짜 입력 및 클릭 ##
remDr$findElement(using = "name",value = "day")$setElementAttribute("value", d)
remDr$findElement(using= "class", value="mdl-button__ripple-container")$clickElement()
## 날짜 입력 및 클릭 ##
Sys.sleep(1)
webElem <- remDr$findElements(using = "class", value = "mdl-chip__text")
resHeaders <- unlist(lapply(webElem, function(x){x$getElementText()}))
if(length(webElem) == 240) {
data_part = matrix(nrow = 10,ncol = 24)
count = 0
for (i in 0:23) {
for (j in 1:10) {
count = count + 1
data_part[j,i+1] = resHeaders[count]
}
}
colnameis = c("H00","H01","H02","H03","H04","H05","H06",
"H07","H08","H09","H10","H11","H12","H13",
"H14","H15","H16","H17","H18","H19","H20",
"H21","H22","H23")
data_part <- as.data.frame(data_part)
colnames(data_part) <- colnameis
data_part$date = d
data_part$site = "zum"
data_part$rank = seq(1,10)
write.table(data_part,"./zum.csv",sep=",",row.names = FALSE,append = TRUE,quote = FALSE)
}
if(aa %% 30 == 0){
remDr$quit()
Sys.sleep(3)
remDr$open()
getUrl = "http://rank.ezme.net/zum"
remDr$navigate(getUrl)
Sys.sleep(3)
next
}
}
[소스 코드 - 코로나 관련 키워드 추출 및 워드클라우드 시각화 코드]
## 명사 추출 함수 로드 (시작) ##
sub_extractNoun <- function(santence = santence, stopword = stopword){
# 보통 명사 추출
text <- extractNoun(santence)
# 남아있는 특수문자, 숫자, 기호, 무의미한 자/모음 등을 제거
text <- gsub('[0-9a-zA-Z~!@#$%^&*()_+=?ㅜㅠㄱ-ㅎㅏ-ㅣ.<>‘’]','',text)
# 불용어로 끝나는 단어 제거 (불필요한 조사 등을 제거하기 위함 -> 지속적인 재귀 호출을 이용하여 반복 처리)
for (i in stopword) {
text <- str_replace_all(string = text,pattern = paste0(i,"$"),"")
}
# 결과 리턴
return(text)
}
data_full <- data.frame()
t_fn <- Sys.glob("./NEWS_OUTPUT/*")
count = 0
for (i in t_fn) {
date = str_split(str_split(i,simplify = T,pattern = "./NEWS_OUTPUT/Naver_News_Keyword_홈트레이닝_")[2],
pattern="day_res.csv",simplify = T)[1]
data_part <- fread(i,encoding = "UTF-8")
if(dim(data_part)[1] == 0 && dim(data_part)[2] == 0){
next
}
# count = count + 1
data_part$date = date
# data_part$newsnumber = count
data_full <- rbind(data_full,data_part)
}
tail(data_full)
colnames(data_full)
data_full <- data_full %>%
mutate(newsnumber = 1:nrow(data_full))
nounFull <- data.frame()
for (i in 1:dim(data_full)[1]) {
print(i)
nounPart <- as.data.frame(extractNoun(data_full$contentInfo[i]))
colnames(nounPart)[1] = "word"
nounPart$date = data_full$date[i]
nounPart$newsnumber = i
nounFull <- rbind(nounFull,nounPart)
}
tail(nounFull)
tail(data_full)
nounFullInfo <- dplyr::inner_join(nounFull,data_full,by=c("newsnumber","date"))
head(nounFullInfo)
colnames(nounFullInfo_L1)
nounFullInfo_L1 <- nounFullInfo %>%
dplyr::filter(nchar(word) >= 2) %>%
dplyr::select(-contentInfo,-urlInfo) %>%
dplyr::filter(word == "홈트레이닝")
head(nounFullInfo_L1)
tail(nounFullInfo_L1)
as.Date(nounFullInfo_L1$date,format = "%Y%m%d")
###############
nounFullInfo_L1_before <- nounFullInfo_L1 %>%
dplyr::mutate(date = as.Date(date,format = "%Y%m%d")) %>%
dplyr::filter(date < as.Date("2020-01-20"))
nounFullInfo_L1_after <- nounFullInfo_L1 %>%
dplyr::mutate(date = as.Date(date,format = "%Y%m%d")) %>%
dplyr::filter(date >= as.Date("2020-01-20"))
##########################
nounFullInfo_before <- nounFullInfo %>%
dplyr::mutate(date = as.Date(date,format = "%Y%m%d")) %>%
dplyr::filter(date < as.Date("2020-01-20"))
nounFullInfo_after <- nounFullInfo %>%
dplyr::mutate(date = as.Date(date,format = "%Y%m%d")) %>%
dplyr::filter(date >= as.Date("2020-01-20"))
##########################
##
dim(nounFullInfo_L1_before)[1] / length(unique(nounFullInfo_before$newsnumber))
dim(nounFullInfo_L1_after)[1] / length(unique(nounFullInfo_after$newsnumber))
length(unique(nounFullInfo_L1_before$newsnumber)) / length(unique(nounFullInfo_before$newsnumber))
length(unique(nounFullInfo_L1_after$newsnumber)) / length(unique(nounFullInfo_after$newsnumber))
##
####################################################
nounFullInfo_L2_before2 <- nounFullInfo %>%
dplyr::mutate(date = as.Date(date,format = "%Y%m%d")) %>%
dplyr::filter(date < as.Date("2020-01-20"))
before_newscount = length(unique(nounFullInfo_L2_before2$newsnumber))
nounFullInfo_L2_after2 <- nounFullInfo %>%
dplyr::mutate(date = as.Date(date,format = "%Y%m%d")) %>%
dplyr::filter(date >= as.Date("2020-01-20"))
after_newscount = length(unique(nounFullInfo_L2_after2$newsnumber))
####################################################
nounFullInfo_L2_before <- nounFullInfo %>%
dplyr::filter(nchar(word) >= 2) %>%
dplyr::select(-contentInfo,-urlInfo) %>%
dplyr::mutate(date = as.Date(date,format = "%Y%m%d")) %>%
dplyr::filter(date < as.Date("2020-01-20")) %>%
dplyr::group_by(word) %>%
dplyr::summarise(freq = n(),
freqOfTotalNews = n() / before_newscount) %>%
dplyr::arrange(desc(freq))
head(nounFullInfo_L2_before)
nounFullInfo_L2_after <- nounFullInfo %>%
dplyr::filter(nchar(word) >= 2) %>%
dplyr::select(-contentInfo,-urlInfo) %>%
dplyr::mutate(date = as.Date(date,format = "%Y%m%d")) %>%
dplyr::filter(date >= as.Date("2020-01-20")) %>%
dplyr::group_by(word) %>%
dplyr::summarise(freq = n(),
freqOfTotalNews = n() / after_newscount) %>%
dplyr::arrange(desc(freq))
head(nounFullInfo_L2_after)
####################################################
asdf <- dplyr::inner_join(nounFullInfo_L2_before,nounFullInfo_L2_after,by=c("word")) %>%
dplyr::arrange(desc(freqOfTotalNews.y-freqOfTotalNews.x))
####################################################
# 1. 워드클라우드 (전,후)
nounFullInfo_L3_before <- nounFullInfo_L2_before %>%
dplyr::filter(!word %like% "[a-zA-Z1-9]") %>%
dplyr::slice(1:100) %>%
dplyr::mutate(freq = (freq/max(freq)) * 10 ) %>%
dplyr::select(-freq) %>%
dplyr::mutate(freqOfTotalNews = round(freqOfTotalNews * 10,0))
# 플롯 #
hw = wordcloud2(data = nounFullInfo_L3_before,
fontFamily='나눔바른고딕',
minSize = 0,
gridSize = 0)
# 이미지화 이후 저장 #
saveWidget(hw,"covid_before.html",selfcontained = F)
webshot::webshot("covid_before.html","covid_before.png",vwidth = 1200, vheight = 1000, delay = 30)
# 이미지화 이후 저장 #
nounFullInfo_L3_after <- nounFullInfo_L2_after %>%
dplyr::filter(!word %like% "[a-zA-Z1-9]") %>%
dplyr::slice(1:100) %>%
dplyr::mutate(freq = (freq/max(freq)) * 10 ) %>%
dplyr::select(-freq) %>%
dplyr::mutate(freqOfTotalNews = round(freqOfTotalNews * 10,0))
# 플롯 #
hw = wordcloud2(data = nounFullInfo_L3_after,
fontFamily='나눔바른고딕',
minSize = 0,
gridSize = 0)
# 이미지화 이후 저장 #
saveWidget(hw,"covid_after.html",selfcontained = F)
webshot::webshot("covid_after.html","covid_after.png",vwidth = 1000, vheight = 800, delay = 30)
# 이미지화 이후 저장 #
nounFullInfo_L3_join <- asdf %>%
dplyr::filter(!word %like% "[a-zA-Z1-9]") %>%
dplyr::mutate(freq = round((freqOfTotalNews.y - freqOfTotalNews.x)*100),0) %>%
dplyr::slice(1:100) %>%
dplyr::select(-freq.x,-freq.y,-freqOfTotalNews.x,-freqOfTotalNews.y,-`0`)
nounFullInfo_L3_join_L1 <- asdf
colnames(nounFullInfo_L3_join_L1)[1:5] <- c("단어","코로나 이전 총 출현수","코로나 이전 뉴스 1건당 출현빈도","코로나 이후 총 출현수","코로나 이후 뉴스 1건당 출현빈도")
# 플롯 #
hw = wordcloud2(data = nounFullInfo_L3_join,
fontFamily='나눔바른고딕',
minSize = 0,
gridSize = 0)
# 이미지화 이후 저장 #
saveWidget(hw,"covid_after_jointop.html",selfcontained = F)
webshot::webshot("covid_after_jointop.html","covid_after_jointop.png",vwidth = 1000, vheight = 800, delay = 30,selector = '#canvas')
# 이미지화 이후 저장 #
# 2. 막대그래프 (top10)
res_L1 <- asdf %>%
dplyr::slice(1:10)
colnames(res_L1)[1:5] <- c("word","freqBefore","mFreqBefore","freqAfter","mFreqAfter")
#######################
asdf_1 <- res_L1 %>%
dplyr::select(word,freqBefore,mFreqBefore) %>%
dplyr::mutate(group = "코로나 이전")
asdf_2 <- res_L1 %>%
dplyr::select(word,freqAfter,mFreqAfter) %>%
dplyr::mutate(group = "코로나 이후")
colnames(asdf_1)[1:3] <- c("word","freq","mFreq")
colnames(asdf_2)[1:3] <- c("word","freq","mFreq")
asdf_res <- rbind(asdf_1,asdf_2)
asdf_res_L1 <- asdf_res %>%
dplyr::mutate(rows = 1:nrow(asdf_res)) %>%
dplyr::mutate(rows = as.character(rows)) %>%
dplyr::mutate(word = as.factor(word))
glimpse(asdf_res_L1)
#######################
ggplot(asdf_res_L1, aes(x = reorder(as.factor(word), -mFreq, sum), y = mFreq, fill = as.factor(group))) +
geom_bar(stat = "identity", aes(fill = group) , position = "dodge") +
xlab("키워드") + ylab("뉴스 1건당 평균 언급횟수") +
ggtitle("코로나사태 이전 대비 빈도수 증가 명사 TOP 10") +
theme_bw() +
theme(
plot.title = element_text(face = "bold", size = 18, color = "black")
, axis.title.x = element_text(face = "bold", size = 16, colour = "black")
, axis.title.y = element_text(face = "bold", size=16, colour = "black", angle = 90)
, axis.text.x = element_text(face = "bold", size=14, colour = "black")
, axis.text.y = element_text(face = "bold", size=14, colour = "black")
, legend.justification = c(1, 1)
, legend.key = element_blank()
, legend.text = element_text(size = 14, face = "bold")
, legend.title = element_text(face = "bold", size = 14, colour = "black")
, legend.background=element_blank()
, plot.margin = unit(c(0, 8, 0, 0), "mm")
) +
ggsave("./OUT_FIG_20201009/res.png",dpi = 600,width = 12,height = 8)
# 3. 엑셀시트
write.table(nounFullInfo_L2_before,"./OUT_FIG_20201009/코로나 이전 홈트레이닝 기사 키워드 단어 빈도.csv",row.names = F)
write.table(nounFullInfo_L2_after,"./OUT_FIG_20201009/코로나 이후 홈트레이닝 기사 키워드 단어 빈도.csv",row.names = F)
write.table(nounFullInfo_L3_join_L1,"./OUT_FIG_20201009/코로나 이전 대비 이후 홈트레이닝 기사 키워드 단어 빈도 변화 순위.csv",row.names = F)
[결과물]
-
키워드 추출 결과 원본 예시
-
워드 클라우드 결과
참고 문헌
[논문]
- 없음
[보고서]
- 없음
[URL]
- 없음
문의사항
[기상학/프로그래밍 언어]
- sangho.lee.1990@gmail.com
[해양학/천문학/빅데이터]
- saimang0804@gmail.com
'자기계발 > 재능상품' 카테고리의 다른 글
[재능상품] Python을 이용한 웹 크롤링 및 워드 클라우드 시각화 (0) | 2020.12.02 |
---|---|
[재능상품] 리눅스 쉘 스크립트를 이용한 사용자 요구사항 (0) | 2020.12.01 |
[재능상품] 오투잡 : 중국 빅데이터 가공 및 번역 서비스 (0) | 2020.11.27 |
[재능상품] 오투잡 : 딥러닝, 머신러닝의 프로그램 개발, 데이터 알고리즘 (0) | 2020.11.27 |
[재능상품] 오투잡 : 데이터 수집, 파싱, 웹 스크래퍼 (0) | 2020.11.27 |
최근댓글