[python] 使用Jieba工具中文分詞及文本聚類概念

        聲明:因爲擔憂CSDN博客丟失,在博客園簡單對其進行備份,之後兩個地方都會寫文章的~感謝CSDN和博客園提供的平臺。
        前面講述了不少關於Python爬取本體Ontology、消息盒InfoBox、虎撲圖片等例子,同時講述了VSM向量空間模型的應用。可是因爲InfoBox沒有先後文和語義概念,因此效果不是很好,這篇文章主要是爬取百度5A景區摘要信息,再利用Jieba分詞工具進行中文分詞,最後提出文本聚類算法的一些概念知識。
        相關文章:
        [Python爬蟲] Selenium獲取百度百科旅遊景點的InfoBox消息盒
        [python爬蟲] Selenium定向爬取海量精美圖片及搜索引擎雜談
        Python簡單實現基於VSM的餘弦類似度計算
        基於VSM的命名實體識別、歧義消解和指代消解
        [python爬蟲] Selenium定向爬取PubMed生物醫學摘要信息html

 

一. Selenium爬取百度百科摘要

        簡單給出Selenium爬取百度百科5A級景區的代碼:python

 1 # coding=utf-8  
 2 """ 
 3 Created on 2015-12-10 @author: Eastmount  
 4 """  
 5   
 6 import time          
 7 import re          
 8 import os  
 9 import sys
10 import codecs
11 import shutil
12 from selenium import webdriver      
13 from selenium.webdriver.common.keys import Keys      
14 import selenium.webdriver.support.ui as ui      
15 from selenium.webdriver.common.action_chains import ActionChains  
16   
17 #Open PhantomJS  
18 driver = webdriver.PhantomJS(executable_path="G:\phantomjs-1.9.1-windows\phantomjs.exe")  
19 #driver = webdriver.Firefox()  
20 wait = ui.WebDriverWait(driver,10)
21 
22 #Get the Content of 5A tourist spots  
23 def getInfobox(entityName, fileName):  
24     try:  
25         #create paths and txt files
26         print u'文件名稱: ', fileName
27         info = codecs.open(fileName, 'w', 'utf-8')  
28 
29         #locate input  notice: 1.visit url by unicode 2.write files
30         #Error: Message: Element not found in the cache -
31         #       Perhaps the page has changed since it was looked up
32         #解決方法: 使用Selenium和Phantomjs
33         print u'實體名稱: ', entityName.rstrip('\n') 
34         driver.get("http://baike.baidu.com/")  
35         elem_inp = driver.find_element_by_xpath("//form[@id='searchForm']/input")  
36         elem_inp.send_keys(entityName)  
37         elem_inp.send_keys(Keys.RETURN)  
38         info.write(entityName.rstrip('\n')+'\r\n')  #codecs不支持'\n'換行  
39   
40         #load content 摘要
41         elem_value = driver.find_elements_by_xpath("//div[@class='lemma-summary']/div")
42         for value in elem_value:
43             print value.text
44             info.writelines(value.text + '\r\n')
45 
46         #爬取文本信息
47         #爬取全部段落<div class='para'>的內容 class='para-title'爲標題 [省略]
48         time.sleep(2)  
49           
50     except Exception,e:    #'utf8' codec can't decode byte  
51         print "Error: ",e  
52     finally:  
53         print '\n'  
54         info.close() 
55   
56 #Main function  
57 def main():
58     #By function get information
59     path = "BaiduSpider\\"
60     if os.path.isdir(path):
61         shutil.rmtree(path, True)
62     os.makedirs(path)
63     source = open("Tourist_spots_5A_BD.txt", 'r')
64     num = 1
65     for entityName in source:  
66         entityName = unicode(entityName, "utf-8")  
67         if u'故宮' in entityName:   #else add a '?'  
68             entityName = u'北京故宮'
69         name = "%04d" % num
70         fileName = path + str(name) + ".txt"
71         getInfobox(entityName, fileName)
72         num = num + 1
73     print 'End Read Files!'  
74     source.close()  
75     driver.close()
76     
77 if __name__ == '__main__':
78     main()  

        內容以下圖所示,共204個國家5A級景點的摘要信息。這裏就再也不敘述:web

 

二. Jieba中文分詞

        Python中分分詞工具不少,包括盤古分詞、Yaha分詞、Jieba分詞等。
        中文分詞庫:http://www.oschina.net/project/tag/264/segment
        其中它們的基本用法都相差不大,可是Yaha分詞不能處理如「黃琉璃瓦頂」或「圜丘壇」等詞,因此使用告終巴分詞。

        1.安裝及入門介紹
        參考地址:http://www.oschina.net/p/jieba
        下載地址:https://pypi.python.org/pypi/jieba/
        Python 2.0我推薦使用"pip install jieba"或"easy_install jieba"全自動安裝,再經過import jieba來引用(第一次import時須要構建Trie樹,須要等待幾秒時間)。
        安裝時若是出現錯誤"unknown encoding: cp65001",輸入"chcp 936"將編碼方式由utf-8變爲簡體中文gbk。算法


        結巴中文分詞涉及到的算法包括:
        (1) 基於Trie樹結構實現高效的詞圖掃描,生成句子中漢字全部可能成詞狀況所構成的有向無環圖(DAG);
        (2) 採用了動態規劃查找最大機率路徑, 找出基於詞頻的最大切分組合;
        (3) 對於未登陸詞,採用了基於漢字成詞能力的HMM模型,使用了Viterbi算法。

        結巴中文分詞支持的三種分詞模式包括:
        (1) 精確模式:試圖將句子最精確地切開,適合文本分析;
        (2) 全模式:把句子中全部的能夠成詞的詞語都掃描出來, 速度很是快,可是不能解決歧義問題;
        (3) 搜索引擎模式:在精確模式的基礎上,對長詞再次切分,提升召回率,適合用於搜索引擎分詞。
        同時結巴分詞支持繁體分詞和自定義字典方法。

windows

 1 #encoding=utf-8
 2 import jieba
 3 
 4 #全模式
 5 text = "我來到北京清華大學"
 6 seg_list = jieba.cut(text, cut_all=True)
 7 print u"[全模式]: ", "/ ".join(seg_list) 
 8 
 9 #精確模式
10 seg_list = jieba.cut(text, cut_all=False)
11 print u"[精確模式]: ", "/ ".join(seg_list)
12 
13 #默認是精確模式
14 seg_list = jieba.cut(text)
15 print u"[默認模式]: ", "/ ".join(seg_list) 
16 
17 #新詞識別 「杭研」並無在詞典中,可是也被Viterbi算法識別出來了
18 seg_list = jieba.cut("他來到了網易杭研大廈") 
19 print u"[新詞識別]: ", "/ ".join(seg_list)
20 
21 #搜索引擎模式
22 seg_list = jieba.cut_for_search(text) 
23 print u"[搜索引擎模式]: ", "/ ".join(seg_list)

        輸出以下圖所示:python爬蟲

        代碼中函數簡單介紹以下:
        jieba.cut():第一個參數爲須要分詞的字符串,第二個cut_all控制是否爲全模式。
        jieba.cut_for_search():僅一個參數,爲分詞的字符串,該方法適合用於搜索引擎構造倒排索引的分詞,粒度比較細。
        其中待分詞的字符串支持gbk\utf-8\unicode格式。返回的結果是一個可迭代的generator,可以使用for循環來獲取分詞後的每一個詞語,更推薦使用轉換爲list列表。

        2.添加自定義詞典
        因爲"國家5A級景區"存在不少旅遊相關的專有名詞,舉個例子:
        [輸入文本] 故宮的著名景點包括乾清宮、太和殿和黃琉璃瓦等
        [精確模式] 故宮/的/著名景點/包括/乾/清宮/、/太和殿/和/黃/琉璃瓦/等
        [全 模 式] 故宮/的/著名/著名景點/景點/包括/乾/清宮/太和/太和殿/和/黃/琉璃/琉璃瓦/等
        顯然,專有名詞"乾清宮"、"太和殿"、"黃琉璃瓦"(假設爲一個文物)可能因分詞而分開,這也是不少分詞工具的又一個缺陷。可是Jieba分詞支持開發者使用自定定義的詞典,以便包含jieba詞庫裏沒有的詞語。雖然結巴有新詞識別能力,但自行添加新詞能夠保證更高的正確率,尤爲是專有名詞。
        基本用法:jieba.load_userdict(file_name) #file_name爲自定義詞典的路徑
        詞典格式和dict.txt同樣,一個詞佔一行;每一行分三部分,一部分爲詞語,另外一部分爲詞頻,最後爲詞性(可省略,ns爲地點名詞),用空格隔開。
        強烈推薦一篇詞性標註文章,連接以下:
        http://www.hankcs.com/nlp/part-of-speech-tagging.htmlide

 1 #encoding=utf-8
 2 import jieba
 3 
 4 #導入自定義詞典
 5 jieba.load_userdict("dict.txt")
 6 
 7 #全模式
 8 text = "故宮的著名景點包括乾清宮、太和殿和黃琉璃瓦等"
 9 seg_list = jieba.cut(text, cut_all=True)
10 print u"[全模式]: ", "/ ".join(seg_list) 
11 
12 #精確模式
13 seg_list = jieba.cut(text, cut_all=False)
14 print u"[精確模式]: ", "/ ".join(seg_list)
15 
16 #搜索引擎模式
17 seg_list = jieba.cut_for_search(text) 
18 print u"[搜索引擎模式]: ", "/ ".join(seg_list)

        輸出結果以下所示,其中專有名詞連在一塊兒,即"乾清宮"和"黃琉璃瓦"。函數


        3.關鍵詞提取
        在構建VSM向量空間模型過程或者把文本轉換成數學形式計算中,你須要運用到關鍵詞提取的技術,這裏就再補充該內容,而其餘的如詞性標註、並行分詞、獲取詞位置和搜索引擎就再也不敘述了。
        基本方法:jieba.analyse.extract_tags(sentence, topK) 
        須要先import jieba.analyse,其中sentence爲待提取的文本,topK爲返回幾個TF/IDF權重最大的關鍵詞,默認值爲20。工具

 1 #encoding=utf-8
 2 import jieba
 3 import jieba.analyse
 4 
 5 #導入自定義詞典
 6 jieba.load_userdict("dict.txt")
 7 
 8 #精確模式
 9 text = "故宮的著名景點包括乾清宮、太和殿和午門等。其中乾清宮很是精美,午門是紫禁城的正門,午門居中向陽。"
10 seg_list = jieba.cut(text, cut_all=False)
11 print u"分詞結果:"
12 print "/".join(seg_list)
13 
14 #獲取關鍵詞
15 tags = jieba.analyse.extract_tags(text, topK=3)
16 print u"關鍵詞:"
17 print " ".join(tags)

        輸出結果以下,其中"午門"出現3次、"乾清宮"出現2次、"著名景點"出現1次,按照順序輸出提取的關鍵詞。若是topK=5,則輸出:"午門 乾清宮 著名景點 太和殿 向陽"。學習

>>> 
分詞結果:
故宮/的/著名景點/包括/乾清宮/、/太和殿/和/午門/等/。/其中/乾清宮/很是/精美/,/午門/是/紫禁城/的/正門/,/午門/居中/向陽/。
關鍵詞:
午門 乾清宮 著名景點
>>> 


        4.對百度百科獲取摘要分詞
        從BaiduSpider文件中讀取0001.txt~0204.txt文件,分別進行分詞處理再保存。

 1 #encoding=utf-8
 2 import sys
 3 import re
 4 import codecs
 5 import os
 6 import shutil
 7 import jieba
 8 import jieba.analyse
 9 
10 #導入自定義詞典
11 jieba.load_userdict("dict_baidu.txt")
12 
13 #Read file and cut
14 def read_file_cut():
15     #create path
16     path = "BaiduSpider\\"
17     respath = "BaiduSpider_Result\\"
18     if os.path.isdir(respath):
19         shutil.rmtree(respath, True)
20     os.makedirs(respath)
21 
22     num = 1
23     while num<=204:
24         name = "%04d" % num 
25         fileName = path + str(name) + ".txt"
26         resName = respath + str(name) + ".txt"
27         source = open(fileName, 'r')
28         if os.path.exists(resName):
29             os.remove(resName)
30         result = codecs.open(resName, 'w', 'utf-8')
31         line = source.readline()
32         line = line.rstrip('\n')
33         
34         while line!="":
35             line = unicode(line, "utf-8")
36             seglist = jieba.cut(line,cut_all=False)  #精確模式
37             output = ' '.join(list(seglist))         #空格拼接
38             print output
39             result.write(output + '\r\n')
40             line = source.readline()
41         else:
42             print 'End file: ' + str(num)
43             source.close()
44             result.close()
45         num = num + 1
46     else:
47         print 'End All'
48 
49 #Run function
50 if __name__ == '__main__':
51     read_file_cut()

        運行結果以下圖所示:


        5.去除停用詞
        在信息檢索中,爲節省存儲空間和提升搜索效率,在處理天然語言數據(或文本)以前或以後會自動過濾掉某些字或詞,這些字或詞即被稱爲Stop Words(停用詞)。這些停用詞都是人工輸入、非自動化生成的,生成後的停用詞會造成一個停用詞表。可是,並無一個明確的停用詞表可以適用於全部的工具。甚至有一些工具是明確地避免使用停用詞來支持短語搜索的。[參考百度百科]

 1 #encoding=utf-8
 2 import jieba
 3 
 4 #去除停用詞
 5 stopwords = {}.fromkeys(['', '包括', '', ''])
 6 text = "故宮的著名景點包括乾清宮、太和殿和午門等。其中乾清宮很是精美,午門是紫禁城的正門。"
 7 segs = jieba.cut(text, cut_all=False)
 8 final = ''
 9 for seg in segs:
10     seg = seg.encode('utf-8')
11     if seg not in stopwords:
12             final += seg
13 print final
14 #輸出:故宮著名景點乾清宮、太和殿和午門。其中乾清宮很是精美,午門紫禁城正門。
15 
16 seg_list = jieba.cut(final, cut_all=False)
17 print "/ ".join(seg_list)
18 #輸出:故宮/ 著名景點/ 乾清宮/ 、/ 太和殿/ 和/ 午門/ 。/ 其中/ 乾清宮/ 很是/ 精美/ ,/ 午門/ 紫禁城/ 正門/ 。

 

 

三. 基於VSM的文本聚類算法

        這部分主要參考2008年上海交通大學姚清壇等《基於向量空間模型的文本聚類算法》的論文,由於個人實體對齊使用InfoBox存在不少問題,發現對齊中會用到文本內容及聚類算法,因此簡單講述下文章一些知識。

 
        文本聚類的主要依據聚類假設是:同類的文檔類似度較大,而非同類文檔類似度較小。同時使用無監督學習方法,聚類不須要訓練過程以及不須要預先對文檔手工標註類別,所以具備較高的靈活性和自動化處理能力。主要分爲如下部分:
        (1) 預處理經常使用方法
        文本信息預處理(詞性標註、語義標註),構建統計詞典,對文本進行詞條切分,完成文本信息的分詞過程。
        (2) 文本信息的特徵表示
        採用方法包括布爾邏輯型、機率型、混合型和向量空間模型。其中向量空間模型VSM(Vector Space Model)是將文檔映射成向量的形式,(T1, T2, ..., Tn)表示文檔詞條,(W1, W2, ..., Wn)文檔詞條對應權重。創建文本特徵主要用特徵項或詞條來表示目標文本信息,構造評價函數來表示詞條權重,盡最大限度區別不一樣的文檔。
        (3) 文本信息特徵縮減
        VSM文檔特徵向量維數衆多。所以,在文本進行聚類以前,應用文本信息特徵集進行縮減,針對每一個特徵詞的權重排序,選取最佳特徵,包括TF-IDF。推薦向量稀疏表示方法,提高聚類的效果,其中(D1, D2, ..., Dn)表示權重不爲0的特徵詞條。
        (4) 文本聚類
        文本內容表示成數學課分析形勢後,接下來就是在此數學基礎上進行文本聚類。包括基於機率方法和基於距離方法。其中基於機率是利用貝葉斯機率理論,機率分佈方式;基於聚類是特徵向量表示文檔(文檔當作一個點),經過計算點之間的距離,包括層次聚類法和平面劃分法。

       後面我可能也會寫具體的Python聚類算法,VSM計算類似度我前面已經講過。同時,他的實驗數據是搜狐中心的10個大類,包括汽車、財經、IT、體育等,而個人數據都是旅遊,如何進一步聚類劃分,如山川、河流、博物館等等,這是另外一個難點。
        最後仍是那句話:不論如何,但願文章對你有所幫助,若是文章中有錯誤或不足之處,還請海涵~寫文不易,且看且分析。加油!!!
      (By:Eastmount 2015-12-11 深夜3點   http://blog.csdn.net/eastmount/) 
相關文章
相關標籤/搜索