我们会用到一个叫做python-twitter
的Python库,其源代码可以在http://code.google.com/p/python-twitter/下载。正如你猜到的那样,借助它,我们可以使用Python来访问Twitter。Twitter.com实际上是一个和其他人进行交流的通道,其上发表的内容被限制在140个字符以内,发表的一条信息称为推文(tweet)。
有关Twitter API的文档可以在http://dev.twitter.com/doc找到。API文档与Python模块中的关键词并不完全一致。我推荐直接阅读Python文件twitter.py
,以完全理解库的使用方法。有关该模块的安装可以参考附录A。虽然这里只会用到函数库的一小部分,但是使用API可以做更多事情,所以我鼓励读者去探索一下API的所有功能。
示例:发现Twitter源中的共现词 (co-occurring word)
- 收集数据:使用
Python-twitter
模块来访问推文。- 准备数据:编写一个函数来去掉URL、去掉标点、转换成小写并从字符串中建立一个单词集合。
- 分析数据:在Python提示符下查看准备好的数据,确保它的正确性。
- 训练算法:使用本章前面开发的
createTree
与mineTree
函数执行FP-growth算法。- 测试算法:这里不适用。
- 使用算法:本例中没有包含具体应用,可以考虑用于情感分析或者查询推荐领域。
在使用API之前,需要两个证书集合。第一个集合是consumer_key和consumer_secret,当注册开发app时(https://dev.twitter.com/apps/new),可以从Twitter开发服务网站获得。这些key对于要编写的app是特定的。第二个集合是access_token_key和access_token_secret,它们是针对特定Twitter用户的。为了获得这些key,需要查看Twitter-Python 安装包中的get_access_token.py文件(或者从Twitter开发网站中获得)。这是一个命令行的Python脚本,该脚本使用OAuth来告诉Twitter应用程序具有用户的权限来发布信息。一旦完成上述工作之后,可以将获得的值放入前面的代码中开始工作。对于给定的搜索词,下面要使用FP-growth算法来发现推文中的频繁单词集合。要提取尽可能多的推文(1400条)然后放到FP-growth算法中运行。将下面的代码添加到fpGrowth.py
文件中。
程序清单12-6 访问Twitter Python库的代码
import twitterfrom time import sleepimport redef getLotsOfTweets(searchStr): CONSUMER_KEY = /'get when you create an app/' CONSUMER_SECRET = /'get when you create an app/' ACCESS_TOKEN_KEY = /'get from Oauth, specific to a user/' ACCESS_TOKEN_SECRET = /'get from Oauth, specific to a user/' api = twitter.Api(consumer_key=CONSUMER_KEY,consumer_secret=CONSUMER_SECRET,access_token_key=ACCESS_TOKEN_KEY,access_token_secret=ACCESS_TOKEN_SECRET) #you can get 1500 results 15 pages * 100 per page resultsPages = for i in range(1,15): print /"fetching page %d/" % i searchResults = api.GetSearch(searchStr, per_page=100, page=i) resultsPages.append(searchResults) sleep(6) return resultsPages
这里需要导入三个库,分别是twitter
库、用于正则表达式的库,以及sleep
函数。后面会使用正则表示式来帮助解析文本。
函数getLotsOfTweets
处理认证然后创建一个空列表。搜索API可以一次获得100条推文。每100条推文作为一页,而Twitter允许一次访问14页。在完成搜索调用之后,有一个6秒钟的睡眠延迟,这样做是出于礼貌,避免过于频繁的访问请求。print
语句用于表明程序仍在执行没有死掉。
下面来抓取一些推文,在Python提示符下输入:
>>> reload(fpGrowth)<module /'fpGrowth/' from /'fpGrowth.py/'>
接下来要搜索一支名为RIMM的股票:
>>> lotsOtweets = fpGrowth.getLotsOfTweets(/'RIMM/')fetching page 1fetching page 2 . . .
lotsOtweets
列表包含14个子列表,每个子列表有100条推文。可以输入下面的命令来查看推文的内容:
>>> lotsOtweets[0][4].textu/"RIM: Open The Network, Says ThinkEquity: In addition, RIMM needs toreinvent its image, not only demonstrating ... http://bit.ly/lvlV1U/"
正如所看到的那样,有些人会在推文中放入URL。这样在解析时,结果就会比较乱。因此必须去掉URL,以便可以获得推文中的单词。下面程序清单中的一部分代码用来将推文解析成字符串列表,另一部分会在数据集上运行FP-growth算法。将下面的代码添加到 fpGrowth.py
文件中。
程序清单12-7 文本解析及合成代码
def textParse(bigString): urlsRemoved = re.sub(/'(http[s]?:[/][/]|www.)([a-z]|[A-Z]|[0-9]|[.]|[~])*/',/'/', bigString) listOfTokens = re.split(r/'W*/', urlsRemoved) return [tok.lower for tok in listOfTokens if len(tok) > 2]def mineTweets(tweetArr, minSup=5): parsedList = for i in range(14): for j in range(100): parsedList.append(textParse(tweetArr[i][j].text)) initSet = createInitSet(parsedList) myFPtree, myHeaderTab = createTree(initSet, minSup) myFreqList = mineTree(myFPtree, myHeaderTab, minSup, set(), myFreqList) return myFreqList
上述程序清单中的第一个函数来自第4章,此外这里添加了一行代码用于去除URL。这里通过调用正则表达式模块来移除任何URL。程序清单12-7中的另一个函数mineTweets
为每个推文调用textParse
。最后,mineTweets
函数将12.2节中用过的命令封装到一起,来构建FP树并对其进行挖掘。最后返回所有频繁项集组成的列表。
下面看看运行的效果:
>>> reload(fpGrowth)<module /'fpGrowth/' from /'fpGrowth.py/'>Let’s look for sets that occur more than 20 times:>>> listOfTerms = fpGrowth.mineTweets(lotsOtweets, 20)How many sets occurred in 20 or more of the documents?>>> len(listOfTerms)455
我写这段代码的前一天,一家以RIMM股票代码进行交易的公司开了一次电话会议,会议并没有令投资人满意。该股开盘价相对前一天封盘价暴跌22%。下面看下上述情况是否在推文中体现:
>>> for t in listOfTerms:... print tset([u/'rimm/', u/'day/'])set([u/'rimm/', u/'earnings/'])set([u/'pounding/', u/'value/'])set([u/'pounding/', u/'overnight/'])set([u/'pounding/', u/'drops/'])set([u/'pounding/', u/'shares/'])set([u/'pounding/', u/'are/']) . . .set([u/'overnight/'])set([u/'drops/', u/'overnight/'])set([u/'motion/', u/'drops/', u/'overnight/'])set([u/'motion/', u/'drops/', u/'overnight/', u/'value/'])set([u/'drops/', u/'overnight/', u/'research/'])set([u/'drops/', u/'overnight/', u/'value/', u/'research/'])set([u/'motion/', u/'drops/', u/'overnight/', u/'value/', u/'research/'])set([u/'motion/', u/'drops/', u/'overnight/', u/'research/'])set([u/'drops/', u/'overnight/', u/'value/'])
尝试一些其他的minSupport
值或者搜索词也是蛮有趣的。
我们还记得FP树的构建是通过每次应用一个实例的方式来完成的。这里假设已经获得了所有数据,所以刚才是直接遍历所有的数据来构建FP树的。实际上可以重写createTree
函数,每次读入一个实例,并随着Twitter流的不断输入而不断增长树。FP-growth算法还有一个map-reduce版本的实现,它也很不错,可以扩展到多台机器上运行。Google使用该算法通过遍历大量文本来发现频繁共现词,其做法和我们刚才介绍的例子非常类似1。
1. H. Li, Y. Wang, D. Zhang, M. Zhang, E. Chang, “PFP: Parallel FP-Growth for Query Recommendation,” RecSys’08, Proceedings of the 2008 ACM Conference on Recommender Systems; http://infolab.stanford.edu/~echang/recsys08-69.pdf.