前面講述了很多關于Python爬取本體Ontology、消息盒InfoBox、虎撲圖片等例子,同時講述了VSM向量空間模型的應用。但是由于InfoBox沒有前后文和語義概念,所以效果不是很好,這篇文章主要是爬取百度5A景區摘要信息,再利用Jieba分詞工具進行中文分詞,最后提出文本聚類算法的一些概念知識。
一. Selenium爬取百度百科摘要
? ? ? ? 簡單給出Selenium爬取百度百科5A級景區的代碼:
[python]?view plain?copy
- #?coding=utf-8????
- """??
- Created?on?2015-12-10?@author:?Eastmount???
- """????
- ????
- import?time????????????
- import?re????????????
- import?os????
- import?sys??
- import?codecs??
- import?shutil??
- from?selenium?import?webdriver????????
- from?selenium.webdriver.common.keys?import?Keys????????
- import?selenium.webdriver.support.ui?as?ui????????
- from?selenium.webdriver.common.action_chains?import?ActionChains????
- ????
- #Open?PhantomJS????
- driver?=?webdriver.PhantomJS(executable_path="G:\phantomjs-1.9.1-windows\phantomjs.exe")????
- #driver?=?webdriver.Firefox()????
- wait?=?ui.WebDriverWait(driver,10)??
- ??
- #Get?the?Content?of?5A?tourist?spots????
- def?getInfobox(entityName,?fileName):????
- ????try:????
- ????????#create?paths?and?txt?files??
- ????????print?u'文件名稱:?',?fileName??
- ????????info?=?codecs.open(fileName,?'w',?'utf-8')????
- ??
- ????????#locate?input??notice:?1.visit?url?by?unicode?2.write?files??
- ????????#Error:?Message:?Element?not?found?in?the?cache?-??
- ????????#???????Perhaps?the?page?has?changed?since?it?was?looked?up??
- ????????#解決方法:?使用Selenium和Phantomjs??
- ????????print?u'實體名稱:?',?entityName.rstrip('\n')???
- ????????driver.get("http://baike.baidu.com/")????
- ????????elem_inp?=?driver.find_element_by_xpath("//form[@id='searchForm']/input")????
- ????????elem_inp.send_keys(entityName)????
- ????????elem_inp.send_keys(Keys.RETURN)????
- ????????info.write(entityName.rstrip('\n')+'\r\n')??#codecs不支持'\n'換行????
- ????
- ????????#load?content?摘要??
- ????????elem_value?=?driver.find_elements_by_xpath("//div[@class='lemma-summary']/div")??
- ????????for?value?in?elem_value:??
- ????????????print?value.text??
- ????????????info.writelines(value.text?+?'\r\n')??
- ??
- ????????#爬取文本信息??
- ????????#爬取所有段落<div?class='para'>的內容?class='para-title'為標題?[省略]??
- ????????time.sleep(2)????
- ????????????
- ????except?Exception,e:????#'utf8'?codec?can't?decode?byte????
- ????????print?"Error:?",e????
- ????finally:????
- ????????print?'\n'????
- ????????info.close()???
- ????
- #Main?function????
- def?main():??
- ????#By?function?get?information??
- ????path?=?"BaiduSpider\\"??
- ????if?os.path.isdir(path):??
- ????????shutil.rmtree(path,?True)??
- ????os.makedirs(path)??
- ????source?=?open("Tourist_spots_5A_BD.txt",?'r')??
- ????num?=?1??
- ????for?entityName?in?source:????
- ????????entityName?=?unicode(entityName,?"utf-8")????
- ????????if?u'故宮'?in?entityName:???#else?add?a?'?'????
- ????????????entityName?=?u'北京故宮'??
- ????????name?=?"%04d"?%?num??
- ????????fileName?=?path?+?str(name)?+?".txt"??
- ????????getInfobox(entityName,?fileName)??
- ????????num?=?num?+?1??
- ????print?'End?Read?Files!'????
- ????source.close()????
- ????driver.close()??
- ??????
- if?__name__?==?'__main__':??
- ????main()????
? ? ? ? 內容如下圖所示,共204個國家5A級景點的摘要信息。這里就不再敘述:
?
二. Jieba中文分詞
? ? ? ? Python中分分詞工具很多,包括盤古分詞、Yaha分詞、Jieba分詞等。
? ? ? ? 中文分詞庫:中文分詞庫 - 開源軟件 - OSCHINA - 中文開源技術交流社區
? ? ? ? 其中它們的基本用法都相差不大,但是Yaha分詞不能處理如“黃琉璃瓦頂”或“圜丘壇”等詞,所以使用了結巴分詞。
? ? ? ??1.安裝及入門介紹
? ? ? ? 參考地址:jieba首頁、文檔和下載 - Python中文分詞組件 - OSCHINA - 中文開源技術交流社區
? ? ? ? 下載地址:jieba · PyPI
? ? ? ? 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)?搜索引擎模式:在精確模式的基礎上,對長詞再次切分,提高召回率,適合用于搜索引擎分詞。
? ? ? ? 同時結巴分詞支持繁體分詞和自定義字典方法。
?
[python]?view plain?copy
- #encoding=utf-8??
- import?jieba??
- ??
- #全模式??
- text?=?"我來到北京清華大學"??
- seg_list?=?jieba.cut(text,?cut_all=True)??
- print?u"[全模式]:?",?"/?".join(seg_list)???
- ??
- #精確模式??
- seg_list?=?jieba.cut(text,?cut_all=False)??
- print?u"[精確模式]:?",?"/?".join(seg_list)??
- ??
- #默認是精確模式??
- seg_list?=?jieba.cut(text)??
- print?u"[默認模式]:?",?"/?".join(seg_list)???
- ??
- #新詞識別?“杭研”并沒有在詞典中,但是也被Viterbi算法識別出來了??
- seg_list?=?jieba.cut("他來到了網易杭研大廈")???
- print?u"[新詞識別]:?",?"/?".join(seg_list)??
- ??
- #搜索引擎模式??
- seg_list?=?jieba.cut_for_search(text)???
- 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
?
[python]?view plain?copy
- #encoding=utf-8??
- import?jieba??
- ??
- #導入自定義詞典??
- jieba.load_userdict("dict.txt")??
- ??
- #全模式??
- text?=?"故宮的著名景點包括乾清宮、太和殿和黃琉璃瓦等"??
- seg_list?=?jieba.cut(text,?cut_all=True)??
- print?u"[全模式]:?",?"/?".join(seg_list)???
- ??
- #精確模式??
- seg_list?=?jieba.cut(text,?cut_all=False)??
- print?u"[精確模式]:?",?"/?".join(seg_list)??
- ??
- #搜索引擎模式??
- seg_list?=?jieba.cut_for_search(text)???
- print?u"[搜索引擎模式]:?",?"/?".join(seg_list)??
? ? ? ? 輸出結果如下所示,其中專有名詞連在一起,即"乾清宮"和"黃琉璃瓦"。
? ? ? ??3.關鍵詞提取
? ? ? ? 在構建VSM向量空間模型過程或者把文本轉換成數學形式計算中,你需要運用到關鍵詞提取的技術,這里就再補充該內容,而其他的如詞性標注、并行分詞、獲取詞位置和搜索引擎就不再敘述了。
? ? ? ? 基本方法:jieba.analyse.extract_tags(sentence, topK)?
? ? ? ??需要先import jieba.analyse,其中sentence為待提取的文本,topK為返回幾個TF/IDF權重最大的關鍵詞,默認值為20。
?
[python]?view plain?copy
- #encoding=utf-8??
- import?jieba??
- import?jieba.analyse??
- ??
- #導入自定義詞典??
- jieba.load_userdict("dict.txt")??
- ??
- #精確模式??
- text?=?"故宮的著名景點包括乾清宮、太和殿和午門等。其中乾清宮非常精美,午門是紫禁城的正門,午門居中向陽。"??
- seg_list?=?jieba.cut(text,?cut_all=False)??
- print?u"分詞結果:"??
- print?"/".join(seg_list)??
- ??
- #獲取關鍵詞??
- tags?=?jieba.analyse.extract_tags(text,?topK=3)??
- print?u"關鍵詞:"??
- print?"?".join(tags)??
? ? ? ? 輸出結果如下,其中"午門"出現3次、"乾清宮"出現2次、"著名景點"出現1次,按照順序輸出提取的關鍵詞。如果topK=5,則輸出:"午門 乾清宮 著名景點 太和殿 向陽"。
[python]?view plain?copy
- >>>???
- 分詞結果:??
- 故宮/的/著名景點/包括/乾清宮/、/太和殿/和/午門/等/。/其中/乾清宮/非常/精美/,/午門/是/紫禁城/的/正門/,/午門/居中/向陽/。??
- 關鍵詞:??
- 午門?乾清宮?著名景點??
- >>>???
? ? ? ??4.對百度百科獲取摘要分詞
? ? ? ? 從BaiduSpider文件中讀取0001.txt~0204.txt文件,分別進行分詞處理再保存。
?
[python]?view plain?copy
- #encoding=utf-8??
- import?sys??
- import?re??
- import?codecs??
- import?os??
- import?shutil??
- import?jieba??
- import?jieba.analyse??
- ??
- #導入自定義詞典??
- jieba.load_userdict("dict_baidu.txt")??
- ??
- #Read?file?and?cut??
- def?read_file_cut():??
- ????#create?path??
- ????path?=?"BaiduSpider\\"??
- ????respath?=?"BaiduSpider_Result\\"??
- ????if?os.path.isdir(respath):??
- ????????shutil.rmtree(respath,?True)??
- ????os.makedirs(respath)??
- ??
- ????num?=?1??
- ????while?num<=204:??
- ????????name?=?"%04d"?%?num???
- ????????fileName?=?path?+?str(name)?+?".txt"??
- ????????resName?=?respath?+?str(name)?+?".txt"??
- ????????source?=?open(fileName,?'r')??
- ????????if?os.path.exists(resName):??
- ????????????os.remove(resName)??
- ????????result?=?codecs.open(resName,?'w',?'utf-8')??
- ????????line?=?source.readline()??
- ????????line?=?line.rstrip('\n')??
- ??????????
- ????????while?line!="":??
- ????????????line?=?unicode(line,?"utf-8")??
- ????????????seglist?=?jieba.cut(line,cut_all=False)??#精確模式??
- ????????????output?=?'?'.join(list(seglist))?????????#空格拼接??
- ????????????print?output??
- ????????????result.write(output?+?'\r\n')??
- ????????????line?=?source.readline()??
- ????????else:??
- ????????????print?'End?file:?'?+?str(num)??
- ????????????source.close()??
- ????????????result.close()??
- ????????num?=?num?+?1??
- ????else:??
- ????????print?'End?All'??
- ??
- #Run?function??
- if?__name__?==?'__main__':??
- ????read_file_cut()??
? ? ? ? 運行結果如下圖所示:
?
? ? ? ??5.去除停用詞
? ? ? ? 在信息檢索中,為節省存儲空間和提高搜索效率,在處理自然語言數據(或文本)之前或之后會自動過濾掉某些字或詞,這些字或詞即被稱為Stop Words(停用詞)。這些停用詞都是人工輸入、非自動化生成的,生成后的停用詞會形成一個停用詞表。但是,并沒有一個明確的停用詞表能夠適用于所有的工具。甚至有一些工具是明確地避免使用停用詞來支持短語搜索的。[參考百度百科]
?
[python]?view plain?copy
- #encoding=utf-8??
- import?jieba??
- ??
- #去除停用詞??
- stopwords?=?{}.fromkeys(['的',?'包括',?'等',?'是'])??
- text?=?"故宮的著名景點包括乾清宮、太和殿和午門等。其中乾清宮非常精美,午門是紫禁城的正門。"??
- segs?=?jieba.cut(text,?cut_all=False)??
- final?=?''??
- for?seg?in?segs:??
- ????seg?=?seg.encode('utf-8')??
- ????if?seg?not?in?stopwords:??
- ????????????final?+=?seg??
- print?final??
- #輸出:故宮著名景點乾清宮、太和殿和午門。其中乾清宮非常精美,午門紫禁城正門。??
- ??
- seg_list?=?jieba.cut(final,?cut_all=False)??
- print?"/?".join(seg_list)??
- #輸出:故宮/?著名景點/?乾清宮/?、/?太和殿/?和/?午門/?。/?其中/?乾清宮/?非常/?精美/?,/?午門/?紫禁城/?正門/?。??
?
三. 基于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、體育等,而我的數據都是旅游,如何進一步聚類劃分,如山川、河流、博物館等等,這是另一個難點。