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

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

<span style="font-size:18px;">import mechanize
br=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 mechanize
br=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-8
import cookielib
import urllib2
import urllib
cj=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 mechanize
import re
import time
from 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 mechanize
import re
import time
from bs4 import BeautifulSoup
import 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])#取第三列toid
f=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 fnum
1 151717544  224
2 194087284  266
3 200161949  413
4 221056707  935
5 221284131  195
6 221348577  195
summary(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 = "-")








你可能感兴趣的:(利用python采集分析人人网社交网络数据)