Textrank權值提取文本標籤提取

我已經爬取到了指定博主的新浪微博,然後我想從微博中提取出可以代表該博主興趣特徵的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"
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章