三. 终于写到了最后一篇啦
第二步看这里:我是第二步嘻嘻嘻
开源地址:是的没错 我是就那个开源
3.1 分析数据
得到了第二步的两个文件:comment.txt和like.txt
每个文件每一行都是这种格式: A$|$B
而我们想要的好友关系网就是数据结构中的图,我们这里的图采用三元组的思想来存储,即 节点a,节点b,权值
所以我们根据已经得到的两个文件在生成个 relationship.txt
里面存储数据的格式: A$|$B$|$value,这里value就是两者的关系值
那采用算法的思想 :(很重要!!!!)
采用list类型存储:如[ [a, b, value1], [c, d, value2]...... ]
这个命名为relationship,先得到这个数据,最后将这个变量循环写入relationship.txt即可、
得到数据的思想如下:
从comment.txt或者like.txt文件中读一行数据,A $|$ B, 那么遍历relationship,如果A,B没有出现同一个子list中,那么新生成一个子list来记录两者的关系值,如果同时出现在同一个子list,那么改变子list中的关系值,如果是从comment中读的数据那么关系+3,如果是在like中读的文件,那么关系+1
那我们就新建一个文件,创建一个新类
import operator as op
class CalRelationship:
#得到txt文件内容
def get_content(self,txtfile):
file = open(txtfile, encoding='UTF-8')
content = file.read()
file.close()
return content
#开始入口
def start(self):
comments = self.get_content('../comment.txt')
likes = self.get_content('../like.txt')
#开始计算
#评论好友关系+3,点赞好友关系+1
self.cal_relationship_by_data(comments,3)
self.cal_relationship_by_data(likes,1)
if __name__ == '__main__':
# 将关系设置为全局变量以供方便调用
relationships = []
cal = CalRelationship()
cal.start()
#将计算好的关系值写入txt
file = open('relationship.txt', 'w', encoding='UTF-8')
for relationship in relationships:
file.write(relationship[0] + '$|$' + relationship[1] + '$|$' + str(relationship[2]) + '\n')
file.close()
基础算法
#计算关系值的基础方法
def cal_relationship(self,name1,name2,value):
global relationships
# 设置两个好友同时是否存在于三元组的标志
flag = False
for relationship in relationships:
# 如果两个人都在那么改变其关系值,并改变标记值
if name1 in relationship and name2 in relationship:
#存储关系图在三元组 [ [name1,name2,value], [name3,name4,vaule]....]
relationship[2] += value
flag = True
# 如果两好友中一者或都不在三元组内,那么添加
if flag == False and op.eq(name1, name2) == False:
# 第一次进去就有个初值
relationships.append([name1, name2, value])
然后就
#通过评论和点赞计算关系值
def cal_relationship_by_data(self,datas,value):
count = 0
data_list = datas.split('\n')
for element in data_list:
count += 1
data = element.split('$|$')
#最后一个是空
if data[0] == '':
return 0
self.cal_relationship(data[0],data[1],value)
print('已经分析了 '+ str(count)+' 行数据')
现在已经完成绝大部分了,得到的relationship.txt就像这样子
3.2 将数据可视化
这里良心一个数据可视化前端框架 : echarts
使用里面的力引导向图,http://echarts.baidu.com/examples/editor.html?c=graph-force
关于这个的基础使用可以看:echarts3.0之关系图详解
因为要在浏览器打开html界面,需要把数据写入html文件
所以首选用php啊,在html内就可以直接解释岂不美滋滋
在html的script标签下改变node和link即可
刚开始想的是直接读一遍数据然后生成节点的同时动态生成边,尝试了好久,但都没成功,后来一想干嘛要把事情复杂化,可以先读一遍数据先生成全部节点,然后再读一遍数据生成边,果然这样分开就简单多了
关键代码如下
"nodes": [
<?php
$file = fopen('这里修改为第三步得到的txt文件路径','r,ccs=UTF-8');
$id = 0;
$name_id = [];
#生成name_id映射数组
while (! feof($file)) {
#每一行两个名字的标记
$flag_0 = true;
$flag_1 = true;
$line = fgets($file);
$data = explode('$|$', $line);
if($data['0'] == '')
continue;
#便利遍历数组如果该节点id以生成那么不再生成结点
foreach ($name_id as $key => $value) {
#存在则不生成
if($data[0] == $key )
$flag_0 = false;
if($data[1] == $key )
$flag_1 = false;
}
//因为存在自己给自己点赞或者评论的情况,那么关系表里会出现自己和自己的关系值,但只需要一个节点就够了,这里有个巨大无比的坑看下面解释
if($data[0] == $data[1])
$flag_1=false;
if($flag_0){
$name_id["$data[0]"] = $id;
$id++;
}
if($flag_1){
$name_id["$data[1]"] = $id;
$id++;
}
}
#根据name_id生成全部节点
foreach ($name_id as $key => $value) {
?>
{ "id": "<?php echo $value;?>", "category": 0, "name": "<?php echo $key?>"},
<?php }?>
],//数据内容
//接收格式均为json对象数组
"links": [
<?php
#再读一遍数据
$file2 = fopen('这里修改为第三步得到的txt文件路径','r,ccs=UTF-8');
while (! feof($file2)) {
$line = fgets($file2);
$data = explode('$|$', $line);
if($data['0'] == '')
continue;
#根据name_id,生成对应边
?>
{
"source": <?php echo $name_id[$data[0]];?>,//起始节点,0表示第一个节点
"target": <?php echo $name_id[$data[1]];?>, //目标节点,1表示与索引为1的节点进行连接
"lineStyle": {"width":<?php echo (int)$data[2]/100 < 1? 1 : (int)$data[2]/100;?>}
},
<?php
}
?>
]//关系对应
这里有个点需要特别注意的!!!就是生成节点的id必须连续!!!必须连续!!!!不然下面的link的target和source的id就算和节点的id对应上了,但是实际出来的图连接的却不是target的id值,这个大概花了三四个人小时才发现这个问题,爬出来这个给自己挖的巨坑
而会使得id值不连续的原因:会出现自己给自己点赞评论的情况,然后关系文件里就会有 A $|$ A,这时候必须加上判断,两个名字一样时只生成一个节点,不然会生成两个节点,而这个工具不允许节点的name一样,这样后面生成的id会把前面的id覆盖,前面的那个id就没了
然后在自己搭建的web服务器下用浏览器打开该php文件
得到最后的图啦
这是帮我同学做的他的qq好友关系网,觉得他的关系网络比较好看,有特点,所以就用他的了,连线代表两人之间有联系,线的粗细代表两人关系的好坏,为了显示效果和隐私就把名字给去了
上面那块是他的中学同学,下面那坨是大学同学,因为他转过专业,所以大学同学分成了两堆,最右边的是家人
发现中学同学和大学同学竟然被联系起来了,于是好奇心的驱使就给加上了名字,原来是他的室友和他一个大学在同一个地方的高中同学