讀古今文學網 > 機器學習實戰 > 12.4 示例:在Twitter源中發現一些共現詞 >

12.4 示例:在Twitter源中發現一些共現詞

我們會用到一個叫做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)

  1. 收集數據:使用Python-twitter模塊來訪問推文。
  2. 準備數據:編寫一個函數來去掉URL、去掉標點、轉換成小寫並從字符串中建立一個單詞集合。
  3. 分析數據:在Python提示符下查看準備好的數據,確保它的正確性。
  4. 訓練算法:使用本章前面開發的createTreemineTree函數執行FP-growth算法。
  5. 測試算法:這裡不適用。
  6. 使用算法:本例中沒有包含具體應用,可以考慮用於情感分析或者查詢推薦領域。

在使用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 twitter
from time import sleep
import re

def 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 1
fetching page 2
                          .
                          .
                          .  
  

lotsOtweets列表包含14個子列表,每個子列表有100條推文。可以輸入下面的命令來查看推文的內容:

>>> lotsOtweets[0][4].text
u\"RIM: Open The Network, Says ThinkEquity: In addition, RIMM needs to
reinvent 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 t
set([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.