加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

第一章, 介绍:挖掘twitter的数据

发布时间:2020-12-14 03:36:59 所属栏目:大数据 来源:网络整理
导读:mahout_xb的专栏 http://www.voidcn.com/article/p-dbejqdju-oy.html ? 第一章, 介绍:挖掘twitter的数据 分类:?data mining 2012-03-11 11:36 ? 1362人阅读 ? 评论(4) ? 收藏 ? 举报 twitter graphviz python dependencies search import 虽然我们可以从

mahout_xb的专栏

http://www.voidcn.com/article/p-dbejqdju-oy.html


?

第一章, 介绍:挖掘twitter的数据

分类:?data mining ? 1362人阅读? 评论(4)? 收藏? 举报
twitter graphviz python dependencies search import

虽然我们可以从讨论社交网络的APIs,schemaless的设计,或者许多其它的事开始, 但是让我们直接进入一些介绍性的例子,以此来说明去收集和分析社交网站的数据。这是一篇入门章节,目的是激发你的兴趣,让你思索一些问题,而余下的章节会涉及到细节。我们将先将开发环境搭建个,然后马上开始收集个分析一些twitter的数据。

安装Python开发环境

这本书的示例以用python语言来写的,如果你已经安装了新版本的python和easy_install在你的系统上,那你可以跳过本节。如果你没有安装python,坏消息是你可能不是一个python hacker。但是不用担心,你很快就是了,因为python很容易上手。用户在任何的平台都能去下载和安装python在:http://www.python.org/download/,但是强烈建议windows用户安装ActivePython,它自动将python加入到你的系统路径下并且已经带有easy_install。本书的代码在python2.7上测试的。

一旦安装好了python,你就可以在命令行敲下python,启动其交互模式。尝试以下示例1-1

示例1-1,第一个python交互会话

[python]? view plain copy
  1. >>>?print?"Hello?World"??
  2. Hello?World??
  3. >>>?#this?is?a?comment??
  4. ...??
  5. >>>?for?i?in?range(0,10):?#?a?loop??
  6. ...?????print?i,?#?the?comma?suppresses?line?breaks??
  7. ...??
  8. 0?1?2?3?4?5?6?7?8?9??
  9. >>>?numbers?=?[?i?10)?]?#?a?list?comprehension??
  10. >>>?print?numbers??
  11. [0,?1,?2,?3,?4,?5,?6,?7,?8,?9]??
  12. if?10?in?numbers:?#?conditional?logic??
  13. ...?????print?True??
  14. ...?else:??
  15. print?False??
  16. False??

另外一个工具easy_install,类似linux上的安装包管理工具, 它能让你很方便安装python的库,而不用去下载,编译,再安装。你可以下载最新的版本在http://pypi.python.org/pypi/setuptools,针对不同的平台有相关的介绍。一般来说,*nix用户可能要用sudo easy_install在安装,使很系统中所有用户都能用到安装的库,而windows用户,如果按照建议安装了ActivePython, 只需要用easy_install命令就好了。

你配置好了easy_install后,就可以用它来安装NetworkX了--用来构建和分析图的工具,整本书都会用到它。安装时能看到类似的输出:

[plain]? copy
    $?easy_install?networkx??
  1. Searching?for?networkx??
  2. ...truncated?output...??
  3. Finished?processing?dependencies?for?networkx??

有了NetworkX后,你可能用在解析器下直接引入它,但有可能会出错:

copy
    import?networkx??
  1. Traceback?(most?recent?call?last):??
  2. ...?truncated?output?...??
  3. ImportError:?No?module?named?numpy??
当出现ImportError时,意味着缺少相应的库。networkx信赖于numpy,?一个高度优化的科学计算库, 执行easy_install numpy解决此问题。安装完numpy后,你应该可以运行示例1-2:

示例1-2, 用networkx来创建一个图的点和边

copy
    >>>?g=networkx.Graph()??
  1. >>>?g.add_edge(1,2)??
  2. >>>?g.add_node("spam")??
  3. print?g.nodes()??
  4. [1,?'spam']??
  5. print?g.edges()??
  6. [(1,?2)]??

现在,你已经安装了一些核心的python开发工具了,准备好去做一些有趣的任务了。如果你觉得这一节有多要学的,那么很有必要去看看官网的python介绍, 在进入下一节之前。


收集和运用twitter的数据

几乎不可能你不知道twitter,它是一个社会化的微博服务,你可能输入140个字符以下的信息,这些信息被称作tweets。不像社交网络如Facebook和LinkedIn,在那里连接是双向的,twitter有一个不对称的基础框架,叫做“朋友”和“粉丝”。假设你有一个twitter账号,你的朋友是你正关注的人,而你的粉丝是那些关注你的人。当然,你可以去关注所有那些关注你的人,然而,这一般是不会发生的,因为你仅仅想让你的Home Timeline中包含你感兴趣的内容。twitter作为一个重要的现象,因为它庞大的用户数量,以及作为市场动向分析工具,和大量的第三方客户端。它提供了广泛的APIs,虽然你可以用其中的很多,而不用注册,但是它会更有趣去建立和挖掘你自己的社交网络。发点时间去看看twitter的 服务条款,API文档,以及API的约束条件。这本书余下的部分假设你有一个twitter的账号,并且有足够多的朋友和粉丝来作为数据去挖掘。

注:这本书的twitter账号是@SocialWebMining


运用twitter的API

twitter的一小部分网络API包装在一个名为twitter的包中,可以通过easy_install来安装:

copy
    $?easy_install?twitter??
  1. Searching?for?twitter??
  2. Finished?processing?dependencies?for?twitter??

这个包还包含一个方便的命令行工具以及网络聊天机器人, 因此当你安装了这个模块后, 你就可以在shell中敲入“twitter"来得到使用帮助。然而,我们将主要关注python的交互解释器。我们将操作几个实例,但是请注意,你可以跳过文档,因为可以用pydoc再次查看这些文档。*nix用户可以简单的敲入pydoc twitter.Twitter来查看Twitter类的文档,而widows用户需要用python -mpydoc twitter.Twitter.如果你发现你经常查看某个模块的文档, 你可以选择传递一个-w选项给pydoc,这样就可以输出为HTML文件来保存或由浏览器收藏为书签。当然,也可以在解释器中键入help来完成同样的功能,如help(twitter.Twitter).

该进入主题了, 我们来找出人们正在谈论什么, 利用twitter的搜索api来观察趋势。让我们先准备好解释器,初始化一个搜索。尝试示例1-3,如果有疑问,用help()来查看相关文档。

示例1-3,检索twitter的搜索趋势

copy
    import?twitter??
  1. >>>?twitter_search?=?twitter.Twitter(domain="search.twitter.com")??
  2. >>>?trends?=?twitter_search.trends()??
  3. >>>?[?trend['name']?for?trend?in?trends['trends']?]??
  4. [u'#ZodiacFacts',?u'#nowplaying',?u'#ItsOverWhen',?u'#Christoferdrew',??
  5. u'Justin?Bieber',?u'#WhatwouldItBeLike',?u'#Sagittarius',?u'SNL',?u'#SurveySays',??
  6. u'#iDoit2']??
你可能在想,使用twitter的api非常之简单:初始化Twitter类用一个URL,然后调用这个对象上的方法。例如,twitter_search.trends()初始化了一个HTTP请求去得到? http://search.twitter.com/trends.json,你也可以键入这个url到浏览器中得到同样的结果。作为前面解释器章节的进一步,这一节完稿在周六的晚上,因此,SNL(周六夜场秀,一美国娱乐节目)出现在趋势列表中不是巧合。现在可能是一个很好的时机去看看twitter的api文档,后面会多次用到。

得出SNL是一个趋势,下面就是去获取一些关于它的搜索结果,用twitter的搜索api来探索包含SNL的tweets,然后以json的格式将它们打印出来,如示例1-4描述的:

示例1-4,分页显示twitter的搜索结果

copy
    >>>?search_results?=?[]??
  1. for?page?in?range(1,6):??
  2. ...?????search_results.append(twitter_search.search(q="SNL",?rpp=100,?page=page))??

以上代码获取和存储结果为5个连续的片断(页),每页100条记录。它是很有意义的去看一个相应的REST查询? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? http://search.twitter.com/
search.json?&q=SNL&rpp=100&page=1。在REST API和twitter模块之间的映射使得我们很容易用python代码来和twitter服务交互。在执行完这个搜索后,search_results包含了5个对象,每个有100条结果记录,你能够将这些结果用易读的形式打印出来,用python 2.6以后自带的json模块,如示例1-5:

示例1-5,易读的twitter数据以json格式

copy
    import?json??
  1. print?json.dumps(search_results,?sort_keys=True,?indent=1)??
  2. [??
  3. ??{??
  4. ????"completed_in":?0.088122000000000006,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ????"max_id":?11966285265,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ????"next_page":?"?page=2&max_id=11966285265&rpp=100&q=SNL",248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ????"page":?1,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ????"query":?"SNL",248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ????"refresh_url":?"?since_id=11966285265&q=SNL",108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ????"results":?[??
  5. ?????{??
  6. ???????"created_at":?"Sun,?11?Apr?2010?01:34:52?+0000",248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ???????"from_user":?"bieber_luv2",108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ???????"from_user_id":?106998169,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ???????"geo":?null,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ???????"id":?11966285265,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ???????"iso_language_code":?"en",108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ???????"metadata":?{??
  7. ????????"result_type":?"recent"??
  8. ???????},??
  9. ???????"profile_image_url":?"http://a1.twimg.com/profile_images/809471978/DSC00522...",108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ???????"source":?"<a?href="http://twitter.com/">web</a>",248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ???????"text":?"?...truncated...?im?nt?gonna?go?to?sleep?happy?unless?i?see?@justin...",108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ???????"to_user_id":?null??
  10. ?????}??
  11. ???????????????...?output?truncated?-?99?more?tweets?...??
  12. ????],??
  13. ????"results_per_page":?100,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ????"since_id":?0??
  14. ??},248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ???????...?output?truncated?-?4?more?pages?...??
  15. ]??

注意,据2010年下半年的通知,在搜索结果中from_user_id字段不对应真实的twitter用户id,查看Twitter API Issue #214得到更多细节,这个缺点到本书的章节没有任何影响,但是如果你要自己创建一些应用就要注意这点了(值得特别关注)

到本书的后面才会仔细推敲这些结果中的细节(请看第5章),这时候要注意的是返回的结果以results作为关键字,我们能提取这500个tweets的文本到列表中,用下面的方法。示例1-6
用一个双列表推导式,缩进以表明它与嵌套循环没什么区别。

示例1-6, 一个简单的python列表推导式

copy
    >>>?tweets?=?[?r['text']???
  1. for?result?in?search_results???
  2. ...?????????for?r?in?result['results']?]??

列表推导式被经常用到在这本书中,虽然它们很容易产生迷惑如果写在一行,但是将它们以嵌套循环打印出来意思就明了了。这个结果tweets相当于定义一个空的列表tweets,然后调用tweets.append(r['text'])在嵌套循环中。参见“Data Structures"一节在python的官网教程中。列表推导是非常有用的,它们有时候能提供更高的效率比嵌套循环,且更简洁。

频率分析和词汇多样性

对于非结构化文本一个最直接的度量就是词汇丰富性(lexical diversity),即不重复的单词数除以总的单词数目。如示例1-7

示例1-7, tweets的词汇丰富性

copy
    >>>?words?=?[]??
  1. for?t?in?tweets:??
  2. ...?????words?+=?[?w?for?w?in?t.split()?]??
  3. >>>?len(words)?#?total?words??
  4. 7238??
  5. >>>?len(set(words))?#?unique?words??
  6. 1636??
  7. >>>?1.0*len(set(words))/len(words)?#?lexical?diversity??
  8. 0.22602928985907708??
  9. >>>?1.0*sum([?len(t.split())?in?tweets?])/len(tweets)?#?avg?words?per?tweet??
  10. 14.476000000000001??
词汇丰富性值0.23表明四个单词中约有一个是唯一的。已知每条tweet的单词数量是14,也就是说仅有3个单词是唯一的在每条tweet中,不考虑其他因素,也就是说每条tweet载有20%的唯一信息。对于这点,有趣的是tweets中有多少噪音是由于五毛党所造成,有哪些常用单词,又有哪些不常用的单词。单词和它们的频率分布就能解决此问题。虽然这不难解决,我们还是安装一个工具,它提供了内置的频率分布以及其它一些文本分析工具。

自然语言工具集(NLTK)是一个非常受欢迎的模块,这本书中我们将经常用到。它包含大量的文本分析工具,如一般向量计算,信息提取,自然语言处理(NLP)等,虽然说它在商业上和学术上不是最先进的,但它提供了坚实的和广泛的基础,如果这是你第一次来尝试做自然语言处理的话。如果你的项目对质量或效率要求很高的话,NLTK不能满足你的需求,这种情况有三个选择,取决于你能花在这上面的时间和金钱: 1.从开源项目中找替代品,做大量的实验和测试来对比它们的性能 2.白手起家自己制造工具集 3.买一个商业的产品。 其中任何一种都不便宜(如果你相信时间就是金钱)或容易。

NLTK能通过easy_install来安装,但你需要重启解释器才能用它。你能够用cPickle模块来保存你的工作会话在重启前。如示例1-8

示例1-8, 保存数据

copy
    >>>?f?=?open("myData.pickle",?"wb")??
  1. import?cPickle??
  2. >>>?cPickle.dump(words,?f)??
  3. >>>?f.close()??
  4. >>>??
  5. $?easy_install?nltk??
  6. Searching?for?nltk??
  7. ...truncated?output...??
  8. Finished?processing?dependencies?for?nltk??
在安装了NLTK后,你可能想要看一看它的官网,那里有它的文档,也包含Natural Language Processing with Python(O'Reilly)整部书的电子版。


人们正在谈论什么?

尝试去回答人们正在谈论什么是挖掘twitter数据最引人入胜的理由。一个最简单的技术用来解决这个问题的就是频率分析。NLTK简化了这个问题,它提供了文本分析的API,因此让我们减轻工作量,让NLTK来处理细节吧。示例1-9演示了这个查找过程,通过创建频率分布,找出50个最常用的和最不常用的词。

示例1-9, 用NLTK来执行最基本的频率分析

copy
    import?nltk??
  1. >>>?words?=?cPickle.load(open("myData.pickle"))??
  2. >>>?freq_dist?=?nltk.FreqDist(words)??
  3. >>>?freq_dist.keys()[:50]?#?50?most?frequent?tokens??
  4. [u'snl',?u'on',?u'rt',?u'is',?u'to',?u'i',?u'watch',?u'justin',?u'@justinbieber',108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> u'be',?u'the',?u'tonight',?u'gonna',?u'at',?u'in',?u'bieber',?u'and',?u'you',248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> u'watching',?u'tina',?u'for',?u'a',?u'wait',?u'fey',?u'of',?u'@justinbieber:',108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> u'if',?u'with',?u'so',?u"can't",?u'who',?u'great',?u'it',?u'going',248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> u'im',?u':)',?u'snl...',?u'2nite...',?u'are',?u'cant',?u'dress',?u'rehearsal',108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> u'see',?u'that',?u'what',?u'but',?u'tonight!',?u':d',?u'2',?u'will']??
  5. >>>?freq_dist.keys()[-50:]?#?50?least?frequent?tokens??
  6. [u'what?!',?u'whens',?u'where',?u'while',?u'white',?u'whoever',?u'whoooo!!!!',248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> u'whose',?u'wiating',?u'wii',?u'wiig',?u'win...',?u'wink.',?u'wknd.',?u'wohh',?u'won',108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ?u'wonder',?u'wondering',?u'wootwoot!',?u'worked',?u'worth',?u'xo.',?u'xx',?u'ya',248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> u'ya<3miranda',?u'yay',?u'yay!',?u'yau2665',?u'yea',?u'yea.',?u'yeaa',?u'yeah!',108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> u'yeah.',?u'yeahhh.',?u'yes,',?u'yes;)',?u'yess',?u'yess,?u'you!!!!!',248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> u"you'll",?u'you+snl=',?u'you,',?u'youll',?u'youtube??',?u'youu<3',108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> u'youuuuu',?u'yum',?u'yumyum',?u'~',?u'xacxac']??

快速的扫一下示例1-9的结果,你会发现最常用的词比最不常用的词载有更多有用的信息。虽然进一步的工作是让机器来识别,但常用词涉及的实体如人,时间,事件,而不常用的词则大都是噪音其中得不出任何有用信息。

第一点你发现的关于常用词的可能就是SNL排在了第一位,既已知这是基于原始的搜索结果,这就不足为奇了。有趣之处上往后面的词看:有很多谈论是关于Justin Bieber, 有以下词为证,@justinbieber,justin,和 bieber。任何人熟悉SNL的也应该知道“tina”和“fey"的出现决非巧合,鉴于Tina Fey和该节目的长期合作关系。也不难从这些词中推断出Justin Bieber是个有名的人,由于他要上周六晚上的节目,所以许多人非常激动的去搜索他。

这时候,你可能会想, “这样啊,那我可以浏览一些tweets,来推断出结论“, 也许的确可以这样,但你想7*24小时来做这件事吧,或是雇佣别人来做。那么如果是在其他领域,仅靠浏览随机的几条文本是得不出可靠的结论呢?要点是频率分析是非常容易,也很有用的工具,它是如此显而易见而不应被忽略。另外,这种技术一个基本的作用就是能让你回答这个问题,"人们正在谈论什么?”

作为最后观察到的一点,“rt"的出现对于话题的继续是很重要的线索。词“RT”是一个特殊的符号,出现在一条tweet之前代表你正转发某人的tweet.从这个词的高频率,可以推断有大量重复的或是相近的tweet.事实上,这个观察是我们下面分析的基础。


从tweets中抽取关系

因为社交网络是第一个也是最重要的一个关于人们之的联系, 一个方便的存储社交网络数据的形式就是图。让我们用NetworkX来构建一个转发tweet的人们的关系图。我们将在图中直接表明信息的流向,更准确的来说,它是双向图。虽然twitter的API有一些能力去判别和分析转发的状态,但对于下面的例子不太适合,因为我们要向服务器作大量的请求,这将是对有限额的API请求的浪费。

除此之外,我们能通过tweet本身的线索以正则表达式来抽取这些信息。按规定,twitter的人名符号以@符号开头,仅能包含字母,数字和下划线。因此,按转发的规定,我们只需要探索下而的样式:

  • RT 后接用户名
  • via 后接用户名
虽然第5章介绍来一个模块来解析tweets中的实体,示例1-10表明你可以用re模块来编译一个样式,以轻量级的方式来抽取tweet的发起人,而不用其它的库。

示例1-10, 用正则表达式来找到转发者

copy
    import?re??
  1. >>>?rt_patterns?=?re.compile(r"(RT|via)((?:bW*@w+)+)",?re.IGNORECASE)??
  2. >>>?example_tweets?=?["RT?@SocialWebMining?Justin?Bieber?is?on?SNL?2nite.?w00t?!?",248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ...?????"Justin?Bieber?is?on?SNL?2nite.?w00t?!??(via?@SocialWebMining)"]??
  3. in?example_tweets:??
  4. ...?????rt_patterns.findall(t)??
  5. [('RT',?'?@SocialWebMining')]??
  6. [('via',?'?@SocialWebMining')]??

以防不太明显,调用findall返回一个元组列表,每一个元组包含一个匹配的字符串或是空字符串,注意这个正则表达式留一个空格在开头,可以很容易的用strip()来解决,如示例1-11。因为示例的tweets中没有一个包含这两种样式,因此,在每一个元组中包含一个空字符串。

已知,这些由twitter API返回的tweet数据结构中包含发tweet的人,以及上面所示获取转发人的方法,很容易将这些信息载入到NetworkX的图中。让我们创建一个图,结点代表用户,两个结点间的有向边代表一个用户转发的另一个用户的tweet,边本身包含tweet的id和tweet的文本。

示例1-11演示了图创建的过程,基本步骤是,首先概括出一个方法来抽取转发中的用户名,再将每一页的tweets数据放入一个列表中,最后,循环扫描每页的tweets并将边加入图中。虽然我们在后面能将图画出来,但即使不可视化它,我们也很从图的特性中得到很多东西。

示例1-11,建立和分析一个图表明了谁转发了谁的tweet

copy
    import?networkx?as?nx??
  1. import?re??
  2. >>>?g?=?nx.DiGraph()??
  3. >>>??
  4. >>>?all_tweets?=?[?tweet??
  5. ...????????????????in?search_results??
  6. ...?????????????????????for?tweet?in?page["results"]?]??
  7. def?get_rt_sources(tweet):??
  8. ...?????rt_patterns?=?re.compile(r"(RT|via)((?:bW*@w+)+)",153); background-color:inherit; font-weight:bold">return?[?source.strip()??
  9. ...??????????????for?tuple?in?rt_patterns.findall(tweet)??
  10. ...??????????????????for?source?in?tuple??
  11. ...???????????????????????if?source?not?in?("RT",?"via")?]??
  12. in?all_tweets:??
  13. ...?????rt_sources?=?get_rt_sources(tweet["text"])??
  14. if?not?rt_sources:?continue??
  15. for?rt_source?in?rt_sources:??
  16. ...?????????g.add_edge(rt_source,?tweet["from_user"],?{"tweet_id"?:?tweet["id"]})??
  17. >>>?g.number_of_nodes()??
  18. 160??
  19. >>>?g.number_of_edges()??
  20. 125??
  21. >>>?g.edges(data=True)[0]??
  22. (u'@ericastolte',?u'bonitasworld',?{'tweet_id':?11965974697L})??
  23. >>>?len(nx.connected_components(g.to_undirected()))??
  24. 37??
  25. >>>?sorted(nx.degree(g))??
  26. [1,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> 1,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> 1,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> 2,?9,?37]??


图1-1,分布图表明了图中结点的度数,揭露了图的联系


NetworkX内置了非常有用的功能去开始分析twitter数据,但有一点很重要,我们要记住这里分析的数据只很少的一部分关于SNL --成千上万中的500个tweets。从这个图中我们知道, 有160个人转发过,但只有125条边,160/125(约1.28)是一个很重要的线索,告诉我们点的平均度数接近1,意味着虽然一些结点与另外多个结点有联系,但平均是约一个联系一个结点。

调用connected_components显示图中包含了37个子图,且不是完全连通的,输出的度数可能起初看起来有点神秘,但是它实实在在的证明了我们获得的一点:它能告诉我们图的联系性怎么样,而不必去渲染出这个图。在这个示例中,大部分的值是1,意味着大部分结点为的度数是1,即仅与另外一个结点为连接。一些值是在2到9之间,意味着与其他2到9个结点连接。特例是那个度数为37的结点。图中有没有任何连接的结点,也有一个度数为37的结点。图1-1以直方图来表明度数的分布。这条趋势线表明它近似幂律分布(Power Law),有一个很长的“尾巴”。虽然这个长尾的特性在本书中没什么用处,但我们会发现我们建立的很多图中有这个特性,但是我强烈的建议你深入的去挖掘如果你有兴趣的话。一个好的出发点是齐普夫定律(Zipf's Law).

在这本书中,我们将发更多的时间来用自动启发式学习来分析数据。这章作为介绍来激发你的头脑,使得你来考虑用手边简单易行的办法来挖掘数据。来结束这章之前,让我们来可视化这个图,以此确保我们的直觉将我们引向了正确的方向。


虚拟tweet图

Graphviz是一个重要的工具在虚拟化社区。这一节介绍一个可行的方法来可视化tweet数据图:把它们导出为DOT语言,一个简单的文本格式,能够被Graphviz运用。Graphviz的二进制文件可以用于任意的平台,在它的官网上可以下载,无论什么平台其安装也是很方便的。当Graphviz被安装后,*nix用户就可以用easy_install pygraphviz来安装其python接口,windows用户安装PyGraphviz很困难,这里介绍一个简单的方法生成DOT格式输出。

示例1-12介绍了一个方法可用于任意平台

copy
    OUT?=?"snl_search_results.dot"??
  1. try:??
  2. ?????nx.drawing.write_dot(g,?OUT)??
  3. except?ImportError,?e:??
  4. ?????#?Help?for?Windows?users:??
  5. ?????#?Not?a?general-purpose?method,?but?representative?of??
  6. #?the?same?output?write_dot?would?provide?for?this?graph??
  7. #?if?installed?and?easy?to?implement??
  8. ?????dot?=?['"%s"?->?"%s"?[tweet_id=%s]'?%?(n1,?n2,?g[n1][n2]['tweet_id'])???
  9. ?????????for?n1,?n2?in?g.edges()]??
  10. ?????f?=?open(OUT,?'w')??
  11. ?????f.write('strict?digraph?{n%sn}'?%?(';n'.join(dot),))??
  12. ?????f.close()??

DOT格式的输出如示例1-13

示例1-13, DOT语言的输出

copy
    strict?digraph?{??
  1. "@ericastolte"?->?"bonitasworld"?[tweet_id=11965974697];??
  2. "@mpcoelho"?->?"Lil_Amaral"?[tweet_id=11965954427];??
  3. "@BieberBelle123"?->?"BELIEBE4EVER"?[tweet_id=11966261062];??
  4. "@BieberBelle123"?->?"sabrina9451"?[tweet_id=11966197327];??
  5. }??

有了DOT格式的输出,下一步就将它转换为图形了。Graphviz提供了各种布局算法来虚拟化所导出的图;circo,一个工具能渲染图为圆形风格的布局,适用于辐射状的拓扑结图,有一个中心点与其它度数为1的结点为相连。*nix用户,可以用下面的命令将snl_search_results.dot从NetworkX导出为snl_search_results.dot.png,然后就可以用图形查看器找开了。

copy
    $?circo?-Tpng?-Osnl_search_results?snl_search_results.dot??

Windows用户可以用GVedit来渲染这个文本,如图1-3.你可以读到更多的选项关于Graphviz在线上文档。图的可视化证实了我们前面的分析,且度数最高的结点是@justinbieber,这个最多讨论的话题。要明白一点的是,如果我们收集更多的tweets,我们将得到更多的内部相连的子图。进一步的分析留给积极的读者们了,这一章主要是准备好开发环境,并激发读者们探索有趣话题的欲望。

Graphviz会出现在本书的其他章节,如果你认为自己是一个数据分析科学家,它是一个你要掌握的工具。也就是说,我们也将用到其他可视化工具。接下来的章节,我们将涉及其它社交网络数据及分析技术。


综合:用Protovis来可视化转发的tweets.

一个关键的示例脚本综合了这一节的大部分内容,并且增加了一个可视化方法, 这就是这一节要做的。另外输出一些有用的信息到终端,它接受一个搜索关键字作为参数,获取,解析,并弹出浏览器来显示可视化数据作为一个可交互的基于html5的图。可以从这本书的官方代码中找到http://github.com/ptwobrussell/Mining-the-Social-Web/blob/master/python_code/introduction__retweet_visualization.py,强烈建议你试一试。

我们将用再次提到Protovis --这个示例中用到的可视化工具集,在这本书的后面几章中。图1-4是这个示例中Protovis的输出,这只是一个开始,你可以用它做更多。


结束语

这一章是个开始,让你认识到它是多么容易用python的交互解释器来挖掘和分析twitter的数据。在进入下一章之前,它是很重要的让你感觉易于使用python的开发环境,并且强烈建议你熟悉twitter的API和Graphviz.如果你还想尝试其它的,推荐canviz,一个项目目的是将Graphviz的图画到浏览器中。你可能也想调查一个IPython,一个更好的python解释器,提供tab补全,历史追综,以及其它更多功能。在这本书中许多的工作与可执行脚本有关,但是它是很重要的,你去多尝试新主意,去调试等等。



图1-2, Graphviz渲染的图形布局搜索结果


图1-3,windows用户用GVedit代替Graphviz



图1-4,一个可交互的Protovis图

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读