微博词云示例




show with app
  • global.R
  • server.R
  • ui.R
#微博词云实例
# 参阅 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()
    )
  )
)