#微博词云实例
# 参阅 https://zhuanlan.zhihu.com/p/82166549,shiny中使用wordcloud2要用一些特殊的函数。
# https://gist.github.com/AdamSpannbauer/135793c68b90b46f44dbe50364c0edf5
# 开启showcase 模式可以参阅 https://blog.csdn.net/douerw/article/details/115350908
# runApp("weibo",display.mode= "showcase", port=3839)
library(Rweibo)
library(jiebaR)
library(tm)
library(wordcloud2)
#注册应用,只需运行一次,写入本地配置文件
# registerApp(app_name = "RJean", "appid", "access key")
#取得授权,只需运行一次,写入本地配置文件
# roauth <- createOAuth(app_name = "RJean", access_name = "rweibo",
# login = TRUE, username = "username", password = "password")
# 创建授权对象,用缓存的有效授权
roauth <- createOAuth("RJean", "rweibo")
#微博转换为数据框
weibo2dataframe<-function(res){
#i<-1
dt<- data.frame(uid= character(), name= character(),screen_name= character(),
id= character(),text= character(), created_at= character())
for(i in 1:length(res)){
tmp<- data.frame(uid= res[[i]]$user$idstr, name= res[[i]]$user$name,screen_name= res[[i]]$user$screen_name,
id= res[[i]]$idstr,text= res[[i]]$text, created_at= res[[i]]$created_at)
dt<-rbind(dt,tmp)
}
return (dt)
}
#爬虫循环爬取一些微博,转成数据框,做文本挖掘测试
wdt<- data.frame(uid= character(), name= character(),screen_name= character(),
id= character(),text= character(), created_at= character())
for(i in 1:10){
res<- statuses.friends_timeline(roauth,page=i, count = 100)
if(length(res)>0){
tmp<-weibo2dataframe(res)
wdt<-rbind(wdt,tmp)
cat(length(res))
cat("\n")
}else{cat(i); cat("\n");break}
}
#只看中央媒体的主题,要先加关注
#wdt2<-wdt[which(wdt$name %in% c("央视新闻","人民日报","人民网","新浪新闻","新华网","头条新闻","中国新闻网","环球时报","新浪博客","广东税务","珠海税务")),]
wdt2<-wdt
# 现在微博已不能顺利的抓取,改为从云端装入以前抓取的部分微博数据。
# library(RODPS)
# wdt2<-rodps.table.read("weibo")
# 直接从csv读速度快很多。
#wdt2<-read.csv("weibo.csv",encoding="utf-8")
#把微博文本向量转换为语料库
ovid <- Corpus(VectorSource(wdt2$text))
# 之后要对每一条微博进行处理,正则匹配去掉@,去掉标点,去掉里面出现的图片等
s1 <- gsub('[a-zA-Z0-9]','',ovid)
s1 <- gsub('[\\pP+~$`^=|<>~`$^+=|<>¥×]','',s1)
s1 <- gsub('①|②|③|④|⑤|⑥|⑦|⑧|⑨|℃|↓|→|丨','',s1)
#去掉各种副词
s1<-gsub("[的|和|了|来|与|到|由|等|从|以|一|为|在|上|各|去|对|侧|多|并|千|万|年|更|向|这是]","",s1)
#分词
seg<-worker()
seg<=s1
#建立词频
freq2<-freq(segment(s1,seg))
#按词频排序
index <- order(-freq2[,2])
order2<<-freq2[index, ]
# 服务端函数,根据浏览器设定的最低词频过滤参与生成词云的词,并作词云图。
function(input, output, session) {
# 定义一个reactive变量
freq<- reactive({
as.integer(input$freq)
})
wdcloud<-reactive({ paste(input$wdcloud)})
observeEvent(freq(),{
# 这一句执行了,证明触发了
print(paste("event triggered: ",freq()))
updateSliderInput(session, "freq", value = freq())
})
# 更新词云词条数据,定义一个reactive变量order3
order3<- reactive({order2[which(order2$freq>= freq()),]})
# 先输出table,这个是正常的
output$table<-renderDataTable(order3())
# 制作词云图,wordcloud2要用renderWordcloud2而不是renderplot()
output$plot <- renderWordcloud2({ if(wdcloud())
# 注意, order3是个reactive变量,要得到里面返回的值,要用函数调用的形式,加上括号order3()
wordcloud2(order3(),size = 1,minRotation = -pi/3, maxRotation = pi/3,rotateRatio = 0.8,
fontFamily = "微软雅黑", color = "random-light", shape = 'star')
})
#接收浏览器端点击选中的词并返回浏览器,显示在网页底端。
observe({ if(wdcloud())
if (!is.null(input$selected_word)) {
print(input$selected_word)
#using default clicked word input id
output$selected_word = renderText(input$selected_word)
}
})
}
# 浏览器端UI函数,选择最低词频,更新显示词云图。
fluidPage(
# Javascript 处理父窗口传入的参数等。
tags$head(tags$script("
// 记录父窗口,初始为空。
parent = null;
// 处理接收到的消息。
window.addEventListener('message', function(e) {
//alert(e.data);
try{
//记录父窗口以备回发信息
parent = e.source;
//向服务器发送input变量更新消息,//Shiny.setInputValue('freq', e.data);
Shiny.setInputValue('freq', e.data, {priority:'event'});
} catch (error){
alert(error);
}
},false);
//发送消息给父窗口
function sendMessage(msg){
if (parent == null){
//alert('No outer frame!');
} else {
try{
var selected = document.getElementById('selected_word');
parent.postMessage(msg, '*');
//alert('sent!');
} catch(error){
alert(error);
}
}
}
")),
# Application title
titlePanel("微博词云示例"),
sidebarLayout(
# Sidebar with a slider and selection inputs
sidebarPanel(
sliderInput("freq",
"最小词频:",
min = 1, max = 50, value = 10),
checkboxInput("wdcloud","画词云图", value = FALSE)
),
# Show Word Cloud
mainPanel(
dataTableOutput('table'),
hr(),
# # wordcloud2要用wordcloud2Output而不是plotOutput()
wordcloud2Output("plot", width = "100%", height = "600px"),
hr(),
# 根据选中的词用javascript动态生成一个input参数传递到服务器端。
# 并发消息给父窗口,通知选中了哪个词。
tags$script(HTML(
"$(document).on('click', '#canvas', function() {",
'word = document.getElementById("wcSpan").innerHTML;',
"Shiny.onInputChange('selected_word', word);",
"sendMessage(word);",
"});"
)) ,
# 服务器端返回这个选中的词,并显示出来
textOutput("selected_word"),
hr()
)
)
)