`
xiaozhonghua
  • 浏览: 253661 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

震撼的CSDN用户关系图

阅读更多

 

前言

在一次校友聚会上,一个做到世界500强公司高级管理层的校友说:在这个城市,要随便找到一个人扯上关系,我最多通过三个人就能办到。这个社会老混混语出惊人,其道理却深值思考。这个社会是一个人与人组成的巨大的关系网络,每个人都是这个巨大网络中的一个节点。如能充分认识和利用这个网络,我们的工作和事业必将如虎添翼。

 

相信大家都有这样的经历,为了了解软件行业信息或解决开发难题时,都会求搜索CSDN 或Javaeye上的专家。同样,某些时候我们也会通过BLOG或发帖共享自己的知识点,不知不觉成为帮助别人的“专家”。而这些网站用户之间又有“关注”关系、“好友”关系等,其实这也是一个巨大的人际网络、知识网络。这个网络到底有多大,看上去又会如何呢?是否也能大到“三个人就能到达任意点”的程度呢?怀着无比的好奇心情,我萌发了一个念头:用程序图形化的呈现一下这个庞大的人际网络,相信一定会have lots of fun!

 

想法出来后,首先仔细观察了一下CSDN网站的BLOG页面结构和好友信息列表,然后用Java Swing写了一个简单的程序。通过近一周的修改,终于初具雏形!在此首先衷心感谢CSDN提供了这么好的数据,其次感谢博客里的朋友,是让这个图出来就这么好看,是你们给了我无穷的动力!

 

废话不说,先上一张最终效果图:



 继续阐述一下程序设计思路。

 

 

技术准备

 

自己最熟悉Java Swing,于是毫无疑问,用Swing来做。同时对需要图形化呈现,自然是用我比较熟悉的TWaver Java版。准备好JDK6和Netbeans,开始干活。

 

首先设置字体。没办法,我有“雅黑”强迫症,自从听说微软每个雅黑汉字都花费了100美金之后,看见什么都想先弄成雅黑,这里也不例外。还用XP的朋友就不好意思了,不知道字体显示效果如何。在Swing里面设置起来很简单,这里偷懒挑一下,只把几个用到的Component设置字体,然后用SwingUtilities.invokeLater启动主窗体:

 

 

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                //setup swing fonts before start program.
                Font font = new Font("微软雅黑", Font.PLAIN, 12);
                UIManager.put("Label.font", font);
                UIManager.put("Button.font", font);
                UIManager.put("RadioButton.font", font);
                UIManager.put("CheckBox.font", font);
                UIManager.put("TextField.font", font);

                //show main ui.
                MainUI ui = new MainUI();
                ui.setVisible(true);
            }
        });
    }

 

 是我喜欢的雅黑效果,耶!

 


 

抓取网页数据

 

接下来,要解决如何获取CSDN用户信息以及好友信息的问题。观察CSDN网站可以发现,用户的BLOG首页是http://blog.csdn.net/+用户名。例如我的BLOG地址是http://blog.csdn.net/solo。要看本人好友,需要看本人详细信息页面,这个页面URL是:http://hi.csdn.net/solo。在这个页面的右侧有用户好友列表。

 

这样,我们就可以用URL和流来读取页面,并解析其中的好友了。在浏览器查看HTML源码,确定好友列表对应的HTML标志,然后通过以下代码进行解析:


try {
            URL url = new URL(urlString);
            BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));
            String line = reader.readLine();
            while (line != null) {
                line = line.trim();
                if (line.startsWith("<div id=\"space_avatar\">")) {
                    line = reader.readLine().trim();
                    int index = line.indexOf("http");
                    line = line.substring(index);
                    index = line.indexOf("\"");
                    String imageURL = line.substring(0, index);
                    index = line.indexOf("alt=");
                    line = line.substring(index + 5);
                    if (line.contains("\"")) {
                        line = line.substring(0, line.indexOf("\""));
                    }
                    String tooltip = line;

                    UserNode centerNode = addNode(null, tooltip, imageURL, null);
                    return centerNode;
                }

                line = reader.readLine();
            }
        } catch (Exception ex) {
            //ex.printStackTrace();
        }
 

此外,为了防止读取URL的过程阻塞Swing线程造成界面卡壳,把它封装并放在单独的Thread或Runnable中进行,读取结果后,再将结果动态放入界面即可:

 

 

 

public class PageExplorer implements Runnable {
.......
    public void run() {
        try {
            if (parent == null) {
                UserNode centerNode = createCenterNode();
                addChildrenNode(centerNode);
                centerNode.setExplored();
            } else {
                addChildrenNode(parent);
                parent.setExplored();
            }
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(network, "无法获得该用户数据。");
        }
    }
..............
}

 

 

数据显示

 

数据获得后,如何显示是关键。显示效果一定要直观、美观、容易理解。TWaver的拓扑图是不二选择,全图形化的拓扑结构绝对比表格之类的东西更加直观、讨巧。

 

然后定义图形元素。其实只有两个元素,一个是点,一个是线。点表示用户节点,线表示其关系,这里只显示一个简单的朋友关系。 

 

接下来就用TWaver的Node和Link定义两个类,封装节点和连线:


public class UserNode extends ResizableNode {

    private boolean male = !(TWaverUtil.getRandomInt(5) == 0);

    public UserNode() {
        init();
    }

    private void init() {
        this.putBorderVisible(false);

        this.putCustomDraw(true);
        this.putCustomDrawFill(true);
        this.putCustomDrawGradient(false);
        this.putCustomDrawGradient(true);

        this.putLabelColor(Color.white);
        this.putLabelFont(new Font("微软雅黑", Font.PLAIN, 12));
        this.putLabelYOffset(-5);
        this.putLabelHighlightable(false);

        this.putLabelUnderlineColor(Color.white);
        if (male) {
            this.setSize(10, 10);
            this.putCustomDrawGradient(false);
            this.putCustomDrawFill3D(true);
            this.putCustomDrawOutline(false);
            this.putCustomDrawShapeFactory(TWaverConst.SHAPE_RECTANGLE);
            this.putCustomDrawFillColor(Color.green.darker());
        } else {
            this.setSize(15, 15);
            this.putCustomDrawShapeFactory(TWaverConst.SHAPE_CIRCLE);
            this.putCustomDrawOutline(false);
            this.putCustomDrawGradientFactory(TWaverConst.GRADIENT_LINE_NE);
            this.putCustomDrawGradientColor(Color.yellow.brighter());
            this.putCustomDrawFillColor(Color.orange);
        }
    }
..............
}
试了一下自己的朋友关系,效果还不错,可惜就是好友太少了!



 

顺藤摸瓜

 

光显示自己的关系网自然不够,还要能够顺藤摸瓜不断的展开、延伸下去才行。基本思路简单:双击下一个节点,再用前面的方法抓取这个人的网页URL,并将下一层好友再次填入,不断往复、以此类推。这样试了一下,有点意思了:

 


自动布局

 

数据复杂后,没有很好的组织结构是无法看出效果的。TWaver提供了不错的自动布局算法,我就利用了两个:一个是环形的静态自动布局,布局后会静止不动;另外一个是基于弹簧算法的动态布局,节点会动画一样的慢慢调整,很有意思。同时提供了两个按钮进行布局切换。弹簧布局比较生动,在拖动节点过程中可以呈现出不同的姿态:

 


 

 

弹簧布局的参数如下:

 

 

//setup TWaver auto-layout algorithm parameters.
        network.getSpringLayouter().setForceSize(3);
        network.getSpringLayouter().setStepSize(40);
        network.getSpringLayouter().setNodeRepulsionFactor(1);
        network.getSpringLayouter().setLinkRepulsionFactor(30);
        network.getSpringLayouter().start();
        network.getCanvasScrollPane().setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
        network.getCanvasScrollPane().setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

        //when window resized, reset the spring layout limit bounds to canvas view port size.
        network.addComponentListener(new ComponentAdapter() {

            @Override
            public void componentResized(ComponentEvent e) {
                network.getSpringLayouter().setLimitBounds(network.getCanvasScrollPane().getBounds());
            }
        });

 

绘制说明文字

 

想添加一点说明文字,要不然大家都不知道怎么用。传统文字说明太土了,自然不符合本程序的审美和风格。要弄就弄fashion一点。想到了TWaver的Marker机制。这个可以在拓扑图上面任意paint东西,符合我的要求!于是fill一个rectangle然后draw文字:

 

 

public class NoteMarker implements CanvasMarker {

    private Color backgroundColor = new Color(0, 200, 200, 50);
    private Font font = new Font("微软雅黑", Font.BOLD, 12);

    public void mark(Graphics2D g) {
        g.setColor(backgroundColor);
        g.fill3DRect(50, 50, 330, 150, true);
        g.setFont(font);
        g.setColor(Color.white);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        int space = 20;
        int x = 55;
        int y = 65;
        g.drawString("1、双击彩色节点【绿色或黄色】进行关系展开", x, y);
        y += space;
        g.drawString("2、灰色节点为已探索用户", x, y);
        y += space;
        g.drawString("3、绿色节点为Boy,黄色节点为Girl", x, y);
        y += space;
        g.drawString("4、鼠标停留可以tooltip此人的照片和BLOG网址", x, y);
        y += space;
        g.drawString("5、选择“环形布局”或“弹簧布局”进行布局算法切换", x, y);
        y += space;
        g.drawString("6、点击“随机展开几个”按钮随机对几个节点自动展开", x, y);
        y += space;
        g.drawString("7、文本框输入其他CSDN用户名并点击按钮“重新开始”", x, y);
    }
}

 

 

再通过下面代码安装marker:

 

 

//display notes on network canvas with a marker.
network.addCanvasMarker(new NoteMarker());

 

 

效果如下:

 


另外,添加了一个小功能:在鼠标停留一个节点一点时间后,通过tooltip显示此人的照片和URL地址。同时有个惊人的发现:这里竟然可以支持GIF动画!

 

最终效果

 

为了展开方便,添加了一个按钮,可以随意展开几个节点,节省了不少鼠标操作。一阵狂点之后,还真是看出了“人与人的关系”之复杂性了:

 


 



 

程序及源代码下载 

老规矩,有福同享、有难同当。源代码和可执行jar包自然会在此奉上。有兴趣的朋友,可以在此基础上,继续完善功能。哪个哥们有精力的话,可以再做一个JavaEye版的就好了!欢迎大家就此进行讨论!另外如果有时间,我还想做一个Flex版的JavaEye的例子,有兴趣的朋友可以共同参与。

可执行程序(jar包、run.bat)和源代码(java源文件)在此处下载:



请确保使用JDK 6编译和运行,同时保持网络通畅,以便到CSDN网站进行数据抓取。

谢谢!

  • 大小: 506 KB
  • 大小: 31.8 KB
  • 大小: 199.3 KB
  • 大小: 541.3 KB
  • 大小: 384.9 KB
  • 大小: 50.6 KB
  • 大小: 263.8 KB
  • 大小: 1 MB
  • 大小: 660.8 KB
分享到:
评论
54 楼 woods 2010-04-12  
这个更适合用twitter数据来展现:) 赞楼主一个
53 楼 ccyingfu 2010-04-12  
你太强了,我要向你学习~~~
52 楼 NumbCoder 2010-04-12  
相当强大,值得学习!
51 楼 zjf_1103 2010-04-12  
正在学习SWT,用SWT做出来的效果呢,呵呵,赶明大家一起研究一下!
50 楼 xxjglobal 2010-04-12  
效果很不错 楼主的想法很好
49 楼 xbcoil 2010-04-12  
没写过 swing 不过看了以后.感触还是很深的.
48 楼 slam33661490 2010-04-12  
很好很强大
47 楼 ChinaEstone 2010-04-12  
很好的思路,呵呵。
46 楼 cyberniuniu 2010-04-12  
楼主的确是很强,再把界面稍微美化一下就更好了,swing支持换肤,你可以用免费的substance look and feel,那就更漂亮了。
45 楼 snow8261 2010-04-12  
确实很不错啊!
44 楼 zjriso 2010-04-12  
顶一个啊!
43 楼 laitaogood 2010-04-12  


我跟楼主也有共同好友,哈哈
佩服LZ的想象力,套用楼上某位哥们的话说是:技术插上了想象力的翅膀~~
42 楼 leoizumi 2010-04-11  
很佩服LZ...学习中
41 楼 niejieqiang 2010-04-11  
太厉害了!!!!!!
40 楼 CodingMouse 2010-04-11  
超赞!用过 Mindjet MindManager 的朋友就知道,这个几乎就是思维导图。
39 楼 kaki 2010-04-11  
太厉害了!
38 楼 hay 2010-04-11  
点开之后还少了关闭,我觉的应该在中心人物再加个监听事件,再次双击则关闭该用户的人际关系图
37 楼 ChinaZhujia 2010-04-11  
好好学习下
36 楼 xiaobin0530 2010-04-11  
强大。牛B
35 楼 huanyun007 2010-04-11  
So cool.

相关推荐

    markdown图片标签转换器 | 解决CSDN无法导入图片问题

    将markdown格式的图片标签转换为html格式,解决CSDN博客无法导入图片的问题 --------------------------------------------- 使用方法(见压缩包内的 README.md 文件): 1. 将需要转换的文件放到 input 文件夹中 2...

    csdn csdn csdn

    csdn csdn csdn csdn

    学习笔记图片从本地复制到csdn博客出现:外链图片转存失败(源码+jar包)

    我是经常将学习笔记记录在Typora中,然后呢,找个时间将笔记统一发布到csdn博客中,一是为了养成一种写笔记的习惯,二是为了保存自己的笔记,防止放在本地电脑,出现什么意外,然后笔记就不见了(好吧,我承认我遇到过这样的...

    CSDN Share:大会PPT合集下载,纯干货!

    CSDN Share 是一款出色的Android阅读工具,阅读由 CSDN社区用户分享的技术文档。 通过CSDN Share可以在线阅读或离线下载CSDN 举办的各类技术活动的精彩讲义,以及来自CSDN下载社区由用户分享的技术文档。 马上下载...

    CSDN 表情 CSDN 表情

    标题 "CSDN 表情" 暗示了这个压缩包可能包含了CSDN社区常用的表情图片,这些表情通常用于论坛、博客或其他互动平台,帮助用户在文字交流中增加情感表达。CSDN是中国一个知名的IT技术社区,用户们在讨论技术问题或...

    CSDN积分的获取方式

    CSDN积分获取方式的多样性为用户提供了灵活的操作空间,用户需要根据自己的实际情况选择合适的方式进行积分的积累。对于新手而言,前期通过上述方式逐渐积累积分,不仅可以下载到需要的资源,还能渐渐融入这个IT技术...

    CSDN分类专栏图标icon

    综上所述,"CSDN分类专栏图标icon"是CSDN为提升博客分类体验而精心设计的一套图形元素,它们以大写字母"C"为核心,结合多样的颜色和形状变化,体现了IT领域的多样性,并通过静态图片形式提供稳定且高效的用户体验。...

    CSDN好友拓扑图

    本话题涉及到的是“CSDN好友拓扑图”,这是一种可视化工具,用于展示CSDN用户之间的社交关系网络。拓扑图是一种图形化表示各种实体之间相互关系的方法,在这里,它帮助我们理解用户之间的关注和互动情况。 首先,...

    CSDN 博客导出工具, 用于将 CSDN 博客导出为 Markdown / PDF 格式

    CSDN博客导出工具是一款专门针对CSDN平台的实用软件,它的主要功能是帮助用户将个人在CSDN上发表的博客文章批量导出为Markdown或PDF格式。这样的工具对于博主而言非常有价值,因为它提供了备份和整理博客内容的便捷...

    CSDN博客导出工具

    1. **认证与授权**:首先,工具需要获取用户的CSDN账号权限,这通常需要用户登录并授权,以便工具能够访问其博客数据。 2. **数据抓取**:获得授权后,工具会通过API请求获取博客列表和每篇博客的详细内容。 3. **...

    CSDN论坛等级图标logo

    在IT行业中,论坛是程序员和IT从业者交流技术、分享经验的重要平台,而CSDN(China Software Developer Network)作为国内知名的开发者社区,其论坛等级图标是用户参与度和专业水平的一种象征。这些图标通常与用户的...

    csdn插件,可以在浏览器首页显示

    其次,自定义壁纸功能允许用户设置个性化的背景图片,增强浏览体验,同时也能体现csdn的品牌特色。最后,插件整合了csdn的搜索引擎,用户无需离开浏览器首页即可直接进行技术问题的搜索,提高了查找资料的效率。 ...

    CSDN自定义专栏封面

    自定义专栏封面是CSDN为了提升用户个性化体验和栏目识别度而推出的一项功能。通过自定义专栏封面,博主可以更好地展示自己的专业领域,吸引读者关注并增强专栏的视觉效果。 在CSDN上创建或管理个人专栏时,你可以...

    CSDN封面图.zip

    4. **一致性**:在CSDN这样的平台上,如果多篇文章形成系列,封面图应保持一致的风格,以便用户识别出同一作者或系列的内容。 5. **尺寸适配**:考虑到CSDN网站的显示效果,封面图应按照平台推荐的尺寸进行设计,...

    CSDN app(完)

    在Android开发中,图片加载库能够解决内存管理和图片缓存的问题,避免因大图加载导致的内存溢出,同时提供异步加载能力,提高用户体验。 2. **XListView**:这是一个扩展的ListView组件,通常用于实现无限滚动或者...

    CSDN博客提取器

    7、生成的pdf、doc文件支持图片 8、支持进度显示 #################################################### 制作时间:2012年07月17日 - 2012年07月18日 制 作:w397090770 个人博客:...

    csdn_tools插件

    总体来说,csdn_tools插件是CSDN用户的一个强大辅助工具,它不仅优化了用户在CSDN平台的浏览体验,还提升了学习和工作效率。对于热衷于技术分享和交流的开发者来说,这是一个不可或缺的利器。通过持续更新和优化,...

    CSDN论坛发图工具

    【CSDN论坛发图工具】是专为CSDN(China Software Developer Network)社区用户设计的一款实用工具,旨在简化用户在论坛上发布图片的过程,提高互动效率。这款最新的版本相比以前的版本,在功能和用户体验上都有显著...

    CSDN官方图片-片子死全家

    学术论坛图片学术论坛图片学术论坛图片学术论坛图片学术论坛图片学术论坛图片学术论坛图片学术论坛图片学术论坛图片学术论坛图片学术论坛图片学术论坛图片

    CSDN博客下载器

    【CSDN博客下载器】是一款专为CSDN(China Software Developer Network)平台设计的工具,用于批量下载用户在该平台发布的博客文章。这款软件能够帮助用户方便地保存自己或他人的博客内容,便于离线阅读、资料备份...

Global site tag (gtag.js) - Google Analytics