IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    链接:人人网关系数据获取

    qxde01发表于 2013-06-13 23:35:28
    love 0
    注:本文完成于2012-10-23,一直在草稿箱里,今天(2013-06-13)发出 ,代码不知是否还能运行。
    现在社交网络分析非常热火,本人也有极大的兴趣,就以人人网为例,学习社交网络分析的过程。
    首先是数据获取问题,关于人人网的数据获取可以参考这里的R程序:包括登录、好友获取、好友状态及网络图绘制等。本文主要引用了其中的登录程序。
    获取好友数据主要有四个函数:
    • renren_login 登录函数
    • renren_detail 获取好友信息函数(只支持部分好友)
    • renren_friend 获取用户的所有好友的ID
    • friend_detail 调用 renren_detail ,批量获取好友信息
    详细代码如下:
    1. renren_login=function(name="****",pwd="******"){
    2. ##登录函数
    3. library(RCurl)
    4. memory.limit(4000)
    5. myH=c(
    6. "User-Agent"="Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12",
    7. "Accept"="text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    8. "Accept-Language"="zh-cn,zh;q=0.5",
    9. "Accept-Charset"="GB2312,utf-8;q=0.7,*;q=0.7",
    10. "Keep-Alive"="115",
    11. "Connection"="keep-alive",
    12. "Content-Type"="application/x-www-form-urlencoded; charset=UTF-8",
    13. "Pragma"="no-cache",
    14. "Cache-Control"="no-cache")
    15. d=debugGatherer()
    16. cH=getCurlHandle(debugfunction=d$update,verbose=T,
    17. ssl.verifyhost=F,ssl.verifypeer=F,followlocation=T,cookiefile="cc.txt")
    18. pinfo=c("email"=name, "password"=pwd,
    19. "origURL"="http://www.renren.com/Home.do","domain"="renren.com")
    20. pinfo=iconv(pinfo,from="GB18030",to="UTF-8")
    21. ttt=postForm("http://passport.renren.com/PLogin.do",httpheader=myH,.params=pinfo,curl=cH,style="post")
    22. getCurlInfo(cH)[["cookielist"]]
    23. h=getURL("http://www.renren.com",curl=cH,.encoding="gbk")
    24. write(h,"temp.txt")
    25. hh=readLines("temp.txt",encoding="UTF-8")
    26. # file.remove("temp.txt")
    27. rm(h)
    28. hh=hh[grep("user : ",hh)]
    29. hh=gsub("[^0-9]","",hh)
    30. return(list(curl=cH,userid=hh))
    31. }
    32. renren_detail<-function(curl,userid){
    33. ##根据用户的ID获取用户的一些基本信息,这个函数虽短,但BUG比行数最多,因很多用户人人的
    34. ##页面是个性化设置的,此函数也只能获取部分用户的信息。
    35. Myurl<-paste('http://www.renren.com/',userid,'/profile',sep='')
    36. h=getURL(Myurl,curl=curl,.encoding="gbk")
    37. write(h,'h.txt')
    38. h=readLines("h.txt",encoding="UTF-8")
    39. user=unlist(strsplit(h[grep('',h)],'-'))[2]
    40. hi<-grep('profile-summary',h)[1]
    41. if(length(hi)==0)hi<-grep('profile-information',h)[1]
    42. if(length(hi)==0|is.na(hi))hi=10
    43. h1<-h[seq(hi-1,hi+40)]
    44. h2<-gsub('<[^]*>|\t| ', '', h1)
    45. h3<-h2[nchar(h2)>0]
    46. school<-h3[grep('所在',h3)+1]
    47. if(length(school)==0)school=NA
    48. birthday<-h3[grep('生  日:',h3)+1]
    49. if(length(birthday)==0)birthday=NA
    50. constellation<-h3[grep('星  座:',h3)+1]
    51. if(length(constellation)==0)constellation=NA
    52. hometown<-h3[grep('家  乡:',h3)+1]
    53. if(length(hometown)==0)hometown=NA
    54. level<-h3[grep('等  级:',h3)+1]
    55. if(length(level)==0)level=NA
    56. cbind(user=user,userid=userid,school=school,birthday=birthday,constellation=constellation, hometown=hometown,level=level)
    57. }
    58. renren_friend<-function(curl,userid){
    59. ##根据用户的ID获取该用户的所有好友的ID
    60. myurl=paste("http://friend.renren.com/GetFriendList.do?curpage=0&id;=",userid,sep="")
    61. h=getURL(myurl,curl=curl,.encoding="gbk")
    62. write(h,'h.txt')
    63. h=readLines("h.txt",encoding="UTF-8")
    64. ##好友数量
    65. hcount<-as.integer(gsub('[^0-9]','',h[grep('',h)]))
    66. pgs=ceiling(hcount/20)
    67. ##获取好友ID,第一页
    68. cat('正在获取',1,'页\n')
    69. h1<-h[grep('http://www.renren.com/profile.do',h)]
    70. h2<-h1[grep('avatar',h1)]
    71. strsplit(h2,'')
    72. h3<-gsub(']*.>|
      |

      , '', h2)
    73. hid<-gsub('[^0-9]','',h3)
    74. if(pgs>1){
    75. for(pg in 1:(pgs-1)){
    76. cat('正在获取',pg+1,'页\n')
    77. myurl=paste("http://friend.renren.com/GetFriendList.do?curpage=",pg,"&id;=",userid,sep="")
    78. h=getURL(myurl,curl=curl,.encoding="gbk")
    79. write(h,'h.txt')
    80. h=readLines("h.txt",encoding="UTF-8")
    81. ##获取好友ID,第2-pgs页
    82. h1<-h[grep('http://www.renren.com/profile.do',h)]
    83. h2<-h1[grep('avatar',h1)]
    84. strsplit(h2,'')
    85. h3<-gsub(']*.>|
      |

      , '', h2)
    86. hid0<-gsub('[^0-9]','',h3)
    87. hid<-c(hid,hid0)
    88. }
    89. }
    90. return(hid)
    91. }
    92. friend_detail<-function(curl,hid){
    93. ##根据好友ID列表,调用renren_detail批量获取好友的一些信息
    94. n=length(hid)
    95. x<-c()
    96. for(i in 1:n){
    97. cat('正在获取第',i,'个',hid[i],'\n')
    98. x1<-renren_detail(curl,hid[i])
    99. x<-rbind(x,x1)
    100. }
    101. x
    102. }

    好友数据获取过程如下,txt文件保存userid的好友ID及userid好友的好友ID,csv文件保存userid的好友基本信息及userid好友的好友基本信息。
    1. ch=renren_login(name='***@***',pwd='******')
    2. curl=ch$curl
    3. userid=ch$userid

    4. hids<-renren_friend(curl,userid=userid)
    5. write(hids,file=paste(userid,'.txt',sep=''))
    6. write.csv(d1,file=paste(userid,'.csv',sep=''),row.names=F)
    7. n=length(hids)
    8. for(i in 1:n){
    9. hisid<-renren_friend(curl,userid=hids[i])
    10. write(hisid,file=paste(hids[i],'.txt',sep=''))
    11. d<-friend_detail(curl,hisid)
    12. write.csv(d,file=paste(hids[i],'.csv',sep=''),row.names=F)
    13. }

    将所有csv文件保存至同一文件夹下,将所有csv文件合并:
    1. setwd('D:/renren/csv/')
    2. csvnames<-dir()
    3. csvID<-gsub('[^0-9]','',csvnames)
    4. n<-length(csvnames)
    5. MyF<-c()
    6. for(i in 1:n){
    7. csv1<-read.csv(csvnames[i])
    8. nr<-nrow(csv1)
    9. MFID<-rep(csvID[i],nr)
    10. mfrela<-cbind(MFID=MFID,csv1)
    11. MyF<-rbind(MyF,mfrela)
    12. }
    13. write.csv(MyF,file='myfriends.csv',row.names=F)

    此时得到了一个好友数据集(MyF),共16042个好友ID,23727好友对,其中我的好友117个,我的好友中最多好友数998个,最少10个,平均203个,中位数164,其直方图有一个长长的尾线,大部分好友的好友数在50--300之间,占75.21%。其中前64位(37.65%)的好友数占80%,与幂律分布的二八定律还差一定距离。
  • fc<-sort(table(MyF[,1]),decreasing=T)
  • hist(fc, breaks = 12,freq = F, col=5, border="red",ylim=c(0,0.0035),xlab='好友数',main='好友数直方图')
  • lines(density(fc),col='blue')
  • 虚拟世界的好友图谱 - qxde01 - 平行宇宙
    其实在数据集中我的好友及我的好友之间的关系只占很少一部分,将它们提取出来,共有2600好友对。
  • hids<-readLines('MyfriendId.txt') ##包含自己的ID
  • onlymy<-MyF[MyF[,3] %in% hids,]

  • 数据集MyF和onlymy如果作为无向图,都有重复的好友对出现,如好友对A--B和B--A实际上是一对好友,造成了数据冗余。使用package:sqldf中的sqldf函数,利用SQL语句进行剔除(这种办法效率比较高),提出1299行数据,剩余22428(myfno)行。
    1. library(sqldf)
    2. ID<-1:nrow(MyF)
    3. myfs<-cbind(ID,MyF)
    4. same<-sqldf('select A.* from myfs A,myfs B
    5. where A.MFID =B.userid and A.userid=B.MFID and A.ID>B.ID')
    6. sid<-same$ID
    7. myfno<-MyF[-sid,]
    8. write.csv(myfno,'myfirends0.csv',row.names=F)
    目前得到四个数据集:
    • MyF,23727对好友, 部分是双向关系;
    • myfno,22428对好友, 只有单向关系;
    • onlymy,2600对好友,只有我的好友及他们之间的关系对。
    • friendinfo,16042个,好友的基本信息,可作为图的边界。(因数据不是在同一时间段获取,好友信息有变更,要去除重复ID)

    1. MyF<-read.csv('myfriends.csv')
    2. myfno<-read.csv('myfirends0.csv')
    3. onlymy<-read.csv('myonlyfriend.csv')
    4. friendinfo<-read.csv('friendinfo.csv')
    另外基本信息中星座中的牧羊座、山羊座统一改为白羊座。获得星座信息的好友数5128个,不足1/3,获得家乡信息的6442个,约40%。
    1. cons<-as.character(friendinfo$constellation)
    2. x<-sort(table(cons),decreasing=T)
    3. a<-x/sum(x)*100
    4. pie(x,labels = paste(names(x),format(a,digits=3),'%',sep=''),col=rainbow(12))
    虚拟世界的好友图谱 - qxde01 - 平行宇宙
    对8307个姓名统计,前15个姓氏占51.25%,前30个占63.81%,前52个占74.14%,频率最高的前30个姓氏分别为"王" 、"张"、 "李" 、"刘" 、"陈"、 "杨"、 "赵" 、"周"、"郭" 、"秦"、 "孙" 、"吴"、 "朱" 、"马" 、"黄"、 "徐"、 "胡"、 "韩" 、"高" 、"宋" 、"许"、 "冯"、 "梁"、 "郑" 、"林"、 "田" 、"杜" 、"吕" 、"袁"、 "崔"。重名最多的几个名字分别为 秦海、王静、 杨广超 、 张静 。
  • b<-readLines('name.txt')
  • b<-substr(a, 1, 1)
  • bb<-sort(table(b),decreasing=F)
  • labels = paste(names(bb[bb>50]),format(bb[bb>50]/sum(bb)*100,digits=2),'%',sep=' ')
  • png('bar1.png',width=1240*0.8,height=1028*0.8)
  • par(mar=c(3,3,1,1))
  • barplot(bb[bb>50],col=rainbow(length(bb[bb>50])),cex.names = 1,horiz=T,legend.text=labels, args.legend=list(x=550,y=25,horiz=F,text.font=2.5))
  • dev.off()
  • 虚拟世界的关系图谱----前传 - qxde01 - 平行宇宙


沪ICP备19023445号-2号
友情链接