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

二. 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) 搜索引擎模式:在精確模式的基礎上,對長詞再次切分,提高召回率,適合用於搜索引擎分詞。
同時結巴分詞支持繁體分詞和自定義字典方法。
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)
輸出如下圖所示:

代碼中函數簡單介紹如下:
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.html
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/)