可视化人人好友关系
目录
- toc
{: toc}
受R分析人人网好友推荐系统和用python进行人人好友分析启发,完全用python的模块和方式实现了一遍,结果搞得好像一点也不Pythonic,倒好像有点继承了之前在lisp下养成的函数式风格……
作为菜鸟深知代码写得不怎么样,写在这里,希望没什么基础的人都能体会到其中我所感受到的乐趣Happy hacking,也欢迎各路高手大牛不吝赐教。
完整代码见github/reverland/scripts/renren.py
必要条件
For Reader:
读者需要有一定python基础,如果没有,不妨花半个小时看看Python简明教程。
For Computer:
我在gentoo linux下完成所有的编写测试,也推荐想尝试的朋友选择linux环境。不过只是推荐,python作为著名的跨平台语言,其代码可以没什么差别的运行在各个平台上,但你需要以下一些必备的东西:
- python 2.7 也许2.5也行,cookielib之前好像不在标准库中,而python3中则有改动。
- networkx 一个分析,操作,绘制网络的python模块。
- matplotlib 经常用来绘图的python模块
怎么安装请自行参照官方网站说明。对后两个模块,建议使用pip安装,这货就相当于个包管理器(一条命令完成搜索下载安装所有操作并自动处理所有依赖)。
最后,还有可选的开发环境:ipython,该程序提供一个功能强大的交互环境,很方便做测试调试探索各种 一次性 工作。
我们要做些什么
从人人网上抓取好友,绘制好友之间的关系图,还可以供进一步分析(貌似没什么好分析的)。
为了实现这点我们需要做到以下几个工作:
- 模拟登录[^1]
- 提取数据以合适数据结构保存
- 制作图像并绘制
模拟登录
人人的模拟登录还是比较简单的。模拟登录最困难的部分就是对要登录网站登录过程的分析。通常办法是通过抓包,用wireshark总有种杀鸡用牛刀的感觉,而且当你像作者一样天天用socks代理时会发现什么也抓不到……所以IE/Chrome/Firefox的开发工具可能更合适。这里用firebug,你可以在火狐扩展中心找到并安装它。
然后在抓包过程中找到用户名^2和登录时请求的服务器。
不过,之前有很多人已经分析过人人的登录过程(一般不会要求验证码,除非登录过于频繁)。你所必须要做的基本上只有两件事:
- 将用户名和密码POST到服务器
- 处理cookie
模拟登录的工具使用python的标准库中的urllib
,urllib2
和cookielib
即可
1 |
import urllib |
如果对这三个标准库不熟悉,建议花时间看看下面两篇教程。不过也许无所谓,代码可以自己解释自己:p。
- urllib2 the missing manual
- cookielib
当浏览器使用POST方法请求服务器时,它将参数经过编码附加到url后传递过去:
http://www.renren.com/ajaxLogin/login&email=username&password=blablabla
登录成功后,还要获取人人中用来作为用户唯一标识额uid(打开人人主页注意url就看到了)并返回,以供将来使用。将来所有的抓取都通过独一无二的uid而非可能重名的姓名。
使用正则抓去uid
import re
我们先写登录函数:
1 |
def login(username, password): |
不妨在ipython中先测试下。
抓取数据
每个人的好友都可以从页面http://friend.renren.com/GetFriendList.do?curpage=0&id=uid
获取,虽然人人已经改版,但这个页面还能用。其中curpage参数的值是页码,id参数的值是拟抓取对象的用户ID。通过循环抓取所有好友并以用户id为键姓名为值保存为字典。
1 |
def getfriends(uid): |
我们再写个获取好友关系字典的函数,为了避免我们每次为了获取字典都要登录抓取。
1 |
def getdict(uid): |
我们还需要一个用来判断两个人关系的函数,来判断我们好友之间的关系。
1 |
def getrelations(uid1, uid2): |
绘制图像
利用以上函数判断好友关系并通过networkx创建一个相应的网络。
1 |
def getgraph(username, password): |
最后是绘图函数,有很多控制图像输出的参数,可能多次调整才会得到想要的图像。在matplotlib画出的图像在窗口中也可以放大缩小选取适当范围。
1 |
def draw_graph(username, password, filename='graph.txt', label_flag=True, remove_isolated=True, different_size=True, iso_level=10, node_size=40): |
把以上函数写进一个文件比如说renren.py,在ipython中导入。
1 |
In[1]: from renren import * |
总结
通过图像你会发现。这些绘图软件的算法相当不错的,你会发现很明显的聚类,这一片是大学同学、这片是小学初中同学,旁边与之联系紧密的是高中同学,这一片孤立的是网友等等。
也许你还会发现你的某些好友竟然相互认识。
抓取下来的数据还可以留待其它研究
你也许会发现有的好友和你的共同好友多得超乎他人,也许发现共同好友分布比较均匀
就这么多这么简单。
希望你也能体会到这个乐趣横生的过程,对我来说,探索和学习的过程是相当意趣盎然的,折腾出来还相当有成就感呢。
What’s more
如果你想让matplotlib显示中文,你需要修改matplotlibrc更改字体。但有一种更通用的办法可以不用修改配置文件。自行google。
ps:这回开高亮了,没感觉和不高亮有啥大区别。感觉还是vim中的高亮漂亮啊,哪天不用pygments直接用vim converto html = =
FootNotes
[^1]:从来没用过api,搞不懂人人api,试着创建个应用Post过去结果认证失败,也没打算申请应用……总之不会搞= =