利用python采集分析人人网社交网络数据

来源:互联网 发布:网络搞笑歌曲你是谁 编辑:程序博客网 时间:2024/04/28 23:00

先做一下小测试,看看人人网首页是哪个form提交数据,提交数据的域有哪些

<span style="font-size:18px;">import mechanizebr=mechanize.Browser()br.open('http://www.renren.com')for form in br.forms():    print form</span>
打印结果为:
<span style="font-size:18px;"><POST http://www.renren.com/PLogin.do application/x-www-form-urlencoded  <TextControl(email=)>  <PasswordControl(password=)>  <CheckboxControl(autoLogin=[true])>  <TextControl(icode=)>  <HiddenControl(origURL=http://www.renren.com/home) (readonly)>  <HiddenControl(domain=renren.com) (readonly)>  <HiddenControl(key_id=1) (readonly)>  <HiddenControl(captcha_type=web_login) (readonly)>  <SubmitControl(<None>=登录) (readonly)>></span>
看起来是第一个form在提交数据,数据域为email和password
<span style="font-size:18px;">import mechanizebr=mechanize.Browser()br.open('http://www.renren.com')br.select_form(nr=0)br['email']='email'#登陆账号,通常为邮箱地址br['password']='password'#登陆密码r=br.submit()print br.title()</span>

可以看到打印出来的title为“人人网-XXX“,XXX为你在人人网的注册名,从而证明登录成功。
当然如果熟悉基础包,使用如下方法也可以达到登陆人人网的目的

<span style="font-size:18px;">#encoding:utf-8import cookielibimport urllib2import urllibcj=cookielib.LWPCookieJar()opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))url='http://www.renren.com/PLogin.do'parms={'email':'xxx','password':'xxx'}parm=urllib.urlencode(parms)req=urllib2.Request(url,parm)response=opener.open(req)print response.geturl()#查看登陆信息,验证登陆成功print response.info()</span>

正式动工,利用mechanize实现自动化登陆与网页内容下载,re或BeautifulSoup实现数据提取,源代码:

<span style="font-size:18px;">#encoding:utf-8'''Created on 2015年1月21日@author: '''import mechanizeimport reimport timefrom bs4 import BeautifulSoup#初始化一个浏览器对象def initBrowser():    #Browser    br = mechanize.Browser()    #options    br.set_handle_equiv(True)    br.set_handle_gzip(True)    br.set_handle_redirect(True)    br.set_handle_referer(True)    br.set_handle_robots(False)    #Follows refresh 0 but not hangs on refresh > 0    br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)    #debugging    #br.set_debug_http(True)    #br.set_debug_redirects(True)    #br.set_debug_responses(True)    #User-Agent    br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')]    return br#登陆人人网def renrenLogin(email,password):    br=initBrowser()    r=br.open('http://www.renren.com')    br.select_form(nr=0)    br['email']=email#登陆账号,通常为邮箱地址    br['password']=password#登陆密码    r=br.submit()    print br.title()    print br.geturl()    return br#获取好友列表页的好友id和姓名def getFriends(page,uid):    friendUrl='http://friend.renren.com/GetFriendList.do?curpage='    friendsUrl=friendUrl+str(page)+'&id='+uid    print 'page-',page,': ',friendsUrl    friendsPage=br.open(friendsUrl).read().decode('utf-8')    soup=BeautifulSoup(friendsPage,from_encoding='utf-8')    friendsCon=soup.find('ol',{'id':'friendListCon'})    friends=friendsCon.find_all('div',{'class':'info'})    #接下来你可以使用正则表达式提取信息    pattern=re.compile('<a href="http://www.renren.com/profile.do\?id=(\d{9})">(.*?)</a>')    for friend in friends:        info=friend.encode('utf-8')        match=pattern.search(info)        if match:            userID=match.group(1)            print 'id:',userID            name=match.group(2)            print 'name:',name    #也可以使用BeautifulSoup来提取信息    for friend in friends:        info=friend.find('a')        href=info['href']        userID=href[-9:len(href)]        print 'id:',userID        name=info.string        print 'name:',name    #如果有下一页,递归处理,循环进行下一页处理    nextPage=soup.find('a',{'title':'下一页'})      if nextPage!=None:        page=page+1        time.sleep(1)#先休息一下        getFriends(page, uid)      email='XXXXX'password='XXXXX'br=renrenLogin(email,password)print br.title()iniUrl=br.geturl()uid=iniUrl[-9:len(iniUrl)]getFriends(0,uid)</span>

就不截取结果图了,自己跑一遍就可以得到自己的所有好友数据。这样就可以将所有好友ID,NAME取到,下一步是通过好友id获取好友的好友,但数据会呈指数级上升,如果我有100个好友,每个好友平均有100个好友,则好友的好友就会有100*100=10000条数据。按照六度分割理论,你和任何一个陌生人之间所间隔的人不会超过五个,100^6=10^12数量级达到百亿级,足以覆盖所有地球人,因此,倘若所有地球人都注册了人人网,最多通过五个中间人你就能够认识任何一个陌生人,如图

以上只抓取到我的好友,为了获取好友的好友,添加一个列表用于记录好友id,然后根据好友id依次抓取好友的好友,并将结果保存到文件,主函数改为:

#encoding:utf-8'''Created on 2015年1月21日@author: '''import mechanizeimport reimport timefrom bs4 import BeautifulSoupimport csv#初始化一个浏览器对象def initBrowser():    #Browser    br = mechanize.Browser()    #options    br.set_handle_equiv(True)    br.set_handle_gzip(True)    br.set_handle_redirect(True)    br.set_handle_referer(True)    br.set_handle_robots(False)    #Follows refresh 0 but not hangs on refresh > 0    br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)    #debugging    #br.set_debug_http(True)    #br.set_debug_redirects(True)    #br.set_debug_responses(True)    #User-Agent    br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')]    return br#登陆人人网def renrenLogin(email,password):    br=initBrowser()    r=br.open('http://www.renren.com')    br.select_form(nr=0)    br['email']=email#登陆账号,通常为邮箱地址    br['password']=password#登陆密码    r=br.submit()    print br.title()    print br.geturl()    return br#获取好友列表页的好友id和姓名def getFriends(page,uid):    friendUrl='http://friend.renren.com/GetFriendList.do?curpage='    friendsUrl=friendUrl+str(page)+'&id='+uid    print 'page-',page,': ',friendsUrl    print br.title()    if page==0:        uname=br.title()[12:]#截取“人人网 - XXX”中的用户名    else:        uname=br.title()[12:-9]#截取“人人网 - XXX的好友”中的用户名    friendsPage=br.open(friendsUrl).read().decode('utf-8')    soup=BeautifulSoup(friendsPage,from_encoding='utf-8')    friendsCon=soup.find('ol',{'id':'friendListCon'})    friends=friendsCon.find_all('div',{'class':'info'})    #接下来你可以使用正则表达式提取信息    pattern=re.compile('<a href="http://www.renren.com/profile.do\?id=(\d{9})">(.*?)</a>')    for friend in friends:        info=friend.encode('utf-8')        match=pattern.search(info)        if match:            userID=match.group(1)            name=match.group(2)            f.write(uid+","+uname+','+userID+','+name+'\n')      #如果有下一页,递归处理,循环进行下一页处理    nextPage=soup.find('a',{'title':'下一页'})      if nextPage!=None:        page=page+1        time.sleep(1)#先休息一下        getFriends(page, uid)      email='XXX'password='XXX'br=renrenLogin(email,password)  print br.title()  iniUrl=br.geturl()  iniId=iniUrl[-9:len(iniUrl)]   f=open('e:/test/renren.csv','a')#追加模式打开 f.write('fromid,fromname,toid,toname\n')  getFriends(0,iniId) #获取朋友 f.flush()f.close()friendsList=[]f=open('e:/test/renren.csv')reader=csv.reader(f)reader.next()#跳过第一行标题行for line in reader:    friendsList.append(line[2])#取第三列toidf=open('e:/test/renren.csv','a')for fid in friendsList:#id为内置变量,避免使用,否则会带来意想不到的意外与麻烦      getFriends(0,fid)  #获取朋友的朋友f.flush()  f.close() 

大功告成,如此就可以循环往复,得到好友的好友数据了。

仍然使用R来进行数据分析和可视化,先看看得到了多少条数据

<span style="font-size:18px;">renren<-read.csv('e:/test/renrendata.csv',sep=',',stringsAsFactors=F,encoding='utf-8',header=F)names(renren)<-c('fromid','fromname','toid','toname')nrow(renren)[1] 43911</span>

接下来对数据进行清洗

<span style="font-size:18px;">renren[,1]<-as.character(renren[,1])renren[,3]<-as.character(renren[,3])renren[,1]=sub('的好友','',renren[,1])#数据中仍然出现少量XXX的好友的情况<span style="font-family:SimSun;">renren[,4]=sub('的好友','',renren[,4])myid=renren[1,1]renren<-renren[renren$fromid!=myid,]#去掉from中的自己renren<-renren[renren$toid!=myid,]#去掉to中的自己length(unique(renren$fromname))#看看我有多少个好友[1] 163</span>
看看朋友的朋友
<span style="font-size:18px;">friends<-table(renren$fromid)frame<-data.frame(friends)nmaes(frame)<-c('id','fnum') head(frame)         id fnum1 151717544  2242 194087284  2663 200161949  4134 221056707  9355 221284131  1956 221348577  195summary(frame$fnum)   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.     8.0   150.8   217.5   265.7   330.0  1248.0 </span></span>
平均每个朋友有250多个朋友,最多的有1200多个朋友,画个图看看分布情况
<span style="font-size:18px;">frame<-frame[order(frame$fnum,decreasing=T),]qplot(1:nrow(frame),fnum,data=frame,geom='line')+xlab('好友数排名')+ylab('好友数')</span>

下文使用igraph包对人人网数据进行社交网络分析。
graph<-graph.data.frame(d=fnet,directed=T,vertices=fnode)graph<-simplify(graph)#去掉重复链接degree<-degree(graph)summary(degree)    Min.  1st Qu.   Median     Mean  3rd Qu.     Max.    1.000    1.000    1.000    2.951    1.000 1248.000 graph<-subgraph(graph,which(degree>3))print(graph)IGRAPH UN-- 1291 12548 -- + attr: name (v/c)plot(graph, layout = layout.fruchterman.reingold, vertex.size = 5, vertex.label = NA,+       edge.color = grey(0.5), edge.arrow.mode = "-")








0 0
原创粉丝点击