我已經爬取到了指定博主的新浪微博,然后我想從微博中提取出可以代表該博主興趣特征的100個關鍵詞,然后由這100個關鍵詞提取出10個標簽,代表博主的興趣。我們此處使用基於Textrank權值的關鍵詞提取方法。
輸入:微博文本集合,如下圖(每一行一條微博)
程序原理如下:(請勿抄襲和轉載)
程序如下:
# -*- coding: utf-8 -*- __author__ = 'Bai Chenjia' import jieba.posseg as pseg import sys import time import networkx as nx import numpy as np reload(sys) sys.setdefaultencoding("utf-8") """ 1.將要處理的微博內容按每條微博進行分詞,去除停用詞,保留名詞,形成一個二級列表返回 如:原始微博為:['這間酒店位於北京東三環,里面擺放很多雕塑,文藝氣息十足', '答謝宴於晚上8點開始'] 經過處理后為:[[ '酒店', '位於, '北京, '東三環, '擺放, '雕塑, '文藝, '氣息' ],[ '答謝', '宴於, '晚上' ]] """ def handel_weibo_data(): #讀取要處理的微博正文提取名詞,去除停用詞 fp = open("f://emotion/mysite/weibo_crawler/chinese_weibo.txt", 'r') weibo_data = [] # 所有的微博,為一個二級列表[[句子][句子][句子]]其中句子已經被分詞去停用詞並保留名詞 for line in fp.readlines(): # 按行處理 contents = [] line = line.strip() line.decode('utf-8') seg_lines = pseg.cut(line) # 分詞標注 for seg_line in seg_lines: # 判斷如果是名詞則保留 if seg_line.flag == 'n' or seg_line.flag == 'nr' or seg_line.flag == 'ns' or seg_line.flag == 'nt' or seg_line.flag == 'nz': contents.append(seg_line.word) # 保留名詞 weibo_data.append(contents) fp.close() return weibo_data """ 2.構建矩陣。 方法:用戶微博文本構建以候選關鍵詞(即選取的名詞)為節點的無向圖 滑動窗口定為一條微博的長度,即倘若兩個詞在同一條微博中出現,就認為它們之間存在較強的語義聯系,共現次數加1 對每一條微博進行同樣的詞對共現次數提取,圖節點間邊的權重記為它們在該用戶微博文本中的共現次數 最后用pagerank算法計算每個單詞的權重,提取權重排名前100的構成該用戶微博的關鍵詞,寫入文件 """ def build_matrix(): ######第一步構建 詞 和 序號的字典 word_index = {} # 詞為鍵,序號為值 index_word = {} # 序號為鍵,詞為值 weibo_data = handel_weibo_data() # 對原始微博數據進行處理, index = 0 for sent in weibo_data: # 對於每句話 for word in sent: # 對每句話中的每個詞 if not word in word_index.keys(): word_index[word] = index index_word[index] = word index += 1 words_number = index #print "words_number", words_number #######第二步構建矩陣 graph = np.zeros((words_number, words_number)) # 構建全零矩陣 for word_list in weibo_data: # 每句話 for i in range(len(word_list)): # 對每句話中的詞進行兩兩配對,將在一條微博中出現的詞對填充到圖中 for j in range(i, len(word_list)): w1 = word_list[i] w2 = word_list[j] # 兩個詞出現在一條微博中 index1 = word_index[w1] index2 = word_index[w2] graph[index1][index2] += 1 # 圖中對應的邊權值加1 graph[index2][index1] += 1 # 無向圖,為對稱矩陣 ######第三步,用networkx中的pagerank算法處理無向圖,得到排序后的關鍵詞 nx_graph = nx.from_numpy_matrix(graph) # 導入networdx scores = nx.pagerank(nx_graph, alpha=0.85) # 調用pagerank算法 sorted_scores = sorted(scores.items(), key=lambda item: item[1], reverse=True) # 得分按照正序排序 key_words = [] # 保存(詞,權值)元組 for index, score in sorted_scores: if index_word[index] == u'網頁' or index_word[index] == u'鏈接' or len(index_word[index]) == 1: continue key_words.append((index_word[index], score)) ########第四步,將排名前100的關鍵詞寫入文件 fp_textrank_result = open('f://emotion/mysite/Label_extract/result_textrank.txt', 'w+') for i in range(100): fp_textrank_result.write(key_words[i][0] + ' ' + str(round(key_words[i][1], 10))) fp_textrank_result.write('\n') fp_textrank_result.close() """ fp_test = open('f://emotion/mysite/Label_extract/test.txt', 'w+') for i in range(100): fp_test.write(key_words[i][0] + '、') fp_test.close() """ print "textrank key word calculate is success..." return key_words """ 3.后處理,提取出標簽 方法:查看權值前100的關鍵詞中是否有相鄰的組合存在,僅抽取出在原文中出現次數超過 2 次的組合計算權重 擴展后的詞串權重,為組成它的詞語的權重之和。按照權重排序后,抽取前 10 作為自動生成的用戶標簽 """ def post_handel_textrank(): # 讀取排名前100的詞和權值 fp_result = open('f://emotion/mysite/Label_extract/result_textrank.txt', 'r') results = {} # 字典存儲詞和權值共100個 words = [] # 存儲100個詞 for result in fp_result.readlines(): result = result.strip() word, score = result.split(' ') # 按空格分割,分別為詞和權值 results[word] = float(score) # str轉為float words.append(word) fp_result.close() #讀取原始微博連成字符串 fp_weibo = open('f://emotion/mysite/weibo_crawler/chinese_weibo.txt', 'r') weibo_list = [] for content in fp_weibo.readlines(): content = content.strip() weibo_list.append(content) fp_weibo.close() #將排名前100的詞組成詞對,查找在原始微博中出現的次數,並記錄 labels = [] for i in range(100): for j in range(i, 100): str1 = words[i] + words[j] str2 = words[j] + words[i] # 連成詞對的兩種不同形式 if words[i] == "網頁" or words[j] == '鏈接' or words[i] == '鏈接' or words[j] == '網頁': continue if words[i] == words[j]: # 剔除噪音和相等的情況 continue str1_count = 0 # str1出現的次數 str2_count = 0 # str2出現的次數 for sent in weibo_list: str1_count += sent.count(str1) str2_count += sent.count(str2) if str1_count > 1: # 如果出現次數大於兩次,則表示該標簽比較穩定,可以加入考慮 #print str1 labels.append((str1, results[words[i]] + results[words[j]])) # 添加元組(詞組,權值) if str2_count > 1: #print str2 labels.append((str2, results[words[i]] + results[words[j]])) # 添加元組(詞組,權值) sorted_labels = sorted(labels, key=lambda w: w[1], reverse=True) # 按照詞組的權值排序 set_sorted_labels = list(set(sorted_labels)) set_sorted_labels.sort(key=sorted_labels.index) # 去重 # 取得testrank值排序前10的標簽組成result_labels作為返回值返回 textrank_result_labels = [] if len(set_sorted_labels) > 10: i = 0 for word1, score1 in set_sorted_labels: if i > 10: break i += 1 if word1 == '人民警': word1 = '人民警察' if word1 == '人溫情': word1 = '人間溫情' if word1 == '女大學': word1 = '女大學生' if word1 == '星沉船': word1 = '東方之星沉船' if word1 == '事件沉船': word1 = '沉船事件' if word1 == '中國工': word1 = '中國工人' if word1 == '北京時': word1 = '北京時間' textrank_result_labels.append((word1, score1)) else: textrank_result_labels = set_sorted_labels[:] print "textrank label extract is success..." for label in textrank_result_labels: print label[0], label[1] return textrank_result_labels if __name__ == '__main__': start = time.clock() #weibo_data = handel_weibo_data() key_words = build_matrix() textrank_result_labels = post_handel_textrank() print "running time:" + str(time.clock()-start) + " s"