[R] PTT推文文化的社群網絡分析(Social Network Analysis),帶你一窺社群網絡中的互動情況
Published in
6 min readMay 11, 2018
爬網+社群網絡分析
PTT是台灣最大的社群網站(http://zh.wikipedia.org/wiki/批踢踢),很多人介紹過我就不多費脣舌,PTT中很特別的功能就是可以推文回應作者,畢竟回文相對來說比較正式,推文感覺更加閒聊的性質.Wxxxxd版相對PTT中的其他版來說,由於有每日發文限制,版友之間更頃向利用推文的方式來互動,而且因為男多女少的緣故,通常女生的推文比較多人推,男生(例如我)可能發文都沒人鳥,然後網友之間彼此也會利用推文互動,本文就是要以圖像化的方式來展現這種推文互動關係。
我知道大家對程式語言沒興趣,所以我先講怎樣看圖:
- 每個圈圈代表一個網友,圈圈的大小代表該網友被“不同人”推文的文章次數
- 箭頭代表的推文的方向 A -> B表示A推B的文章,而且不同大小的圈圈
從圖中來看,可以發現網友之間的互動真的非常密切和多樣,除了幾位人氣王之外,也有很多小團體和出現眾星拱月的情況.人氣王彼此之間的互動也不在少數,相信有逛過wanted版的朋友看起來會更有感觸.至於ID的部分我就隱藏起來了,雖然是這是公開資料,但是畢竟不是每個人都喜歡被別人分析XD
以下講的是做法:本次分析包含資料截取到畫圖都是利用R軟體來實做,用的主要方法包括爬網和社群網絡分析(social network analysis),以下是原始碼.
安裝 Rstudio
當然要用 Docker 比較方便…
docker pull rocker/rstudio
開啟的時候記得要開 root 才能安裝套件
docker run -d -p 8787:8787 -e ROOT=TRUE rocker/rstudio
安裝 ubuntu 套件
sudo apt-get update
sudo apt-get install libxml2-dev
安裝 R 套件
install.packages(c("xml2","XML","httr","stringr", "igraph", "dplyr"));
爬網
library("XML")
library("httr")
library("stringr")
library("igraph")
library("dplyr")##這部分是爬網,先從網頁版PTT中抓下每篇文章的聯結
rm(data)
data <- list()
for( i in 1628:1630){
url <- paste('bbs/Wanted/index', i, '.html', sep='')
html <- content(GET("https://www.ptt.cc/", path = url),as = 'parsed')
htmlParsed <- htmlParse(html, asText=TRUE)
url.list <- xpathSApply(htmlParsed, "//div[@class='title']/a[@href]", xmlAttrs)
data <- rbind(data, url.list[[1]])
}##把一些空值刪掉
data = Filter(function(x) x != "www.ptt.cc",data)##根據每篇文章代碼進去抓作者和推文的資料
popu <- function(link){
html <- content(GET('https://www.ptt.cc', path = data[[link]]), as = 'parsed')
htmlParsed <- htmlParse(html, asText=TRUE)
poster <- xpathApply(htmlParsed,"//div[@class='article-metaline']/span[@class='article-meta-value']",xmlValue)[[1]]
#這邊特別說明一下,因為作者這個欄位很討厭,除了ID之外還有暱稱,要把暱稱刪掉
poster <- str_split_fixed(poster, "\\(",2)[,1]
puller <- xpathApply(htmlParsed,"//div[@class='push']/span[@class='f3 hl push-userid']",xmlValue)
#這個if是排除那些沒人有推文的作者(例如我)
if (length(puller) >0 ){
puller <- as.data.frame(matrix(unlist(puller),nrow = length(puller),T))
edgelist <- merge(poster,puller,all = TRUE)
return (edgelist)
}
}
整理資料
edge = list()
for (l in 1:length(data)){
edge <- rbind(edge, popu(l))
}#依照推文和被推者分組,計算每個pair的數量
edge2 <- group_by(edge,x,V1)
edge2 <- summarise(edge2,weight=n())#from 表示推文者 in 表示被推文的
edge2 <- data.frame(from = edge2$V1, to = edge2$x,weight = edge2$weight)
- 原始的 Edge
- 計算 Weight
最後畫圖
g <- graph.data.frame(edge2,directed = TRUE)#用被推文的數量“in"來決定大小
V(g)$size <- degree(g,mode = ("in"))/2#接下來就是畫圖輸出了
png(filename="org_network.png", height=1080, width=1080)
plot(g, layout = layout.fruchterman.reingold,
vertex.label=NA,
edge.arrow.size = 1
)